From ad76b3026fefc8f516ec717e4cc3640898badba0 Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 09:15:46 +0200 Subject: [PATCH 01/77] docs: brand tone and writing style fixes (#12671) Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- docs/developer-guide/provider.mdx | 14 ++--- .../security-compliance-framework.mdx | 54 +++++++++---------- docs/developer-guide/server-sent-events.mdx | 18 +++---- docs/getting-started/products/prowler-mcp.mdx | 2 +- docs/troubleshooting.mdx | 2 +- docs/user-guide/cli/tutorials/fixer.mdx | 2 +- docs/user-guide/cli/tutorials/misc.mdx | 4 +- docs/user-guide/cli/tutorials/mutelist.mdx | 2 +- .../getting-started-alibabacloud.mdx | 8 +-- .../providers/aws/organizations.mdx | 2 +- .../getting-started-mongodbatlas.mdx | 20 +++---- .../providers/okta/authentication.mdx | 22 ++++---- .../tutorials/prowler-app-findings-triage.mdx | 8 +-- .../tutorials/prowler-app-github-action.mdx | 12 ++--- .../prowler-app-jira-integration.mdx | 4 +- .../user-guide/tutorials/prowler-app-rbac.mdx | 2 +- .../tutorials/prowler-import-findings.mdx | 2 +- 17 files changed, 89 insertions(+), 89 deletions(-) diff --git a/docs/developer-guide/provider.mdx b/docs/developer-guide/provider.mdx index 70fd519505..3d96e41ab5 100644 --- a/docs/developer-guide/provider.mdx +++ b/docs/developer-guide/provider.mdx @@ -25,7 +25,7 @@ For providers supported by Prowler, refer to [Prowler Hub](https://hub.prowler.c Prowler supports several types of providers, each with its own implementation pattern and use case. Understanding these differences is key to designing your provider correctly. -### Classifying your Provider +### Classifying Your Provider Before implementing a new provider, you need to determine which type it belongs to. This classification will guide your implementation approach and help you choose the right patterns and libraries. @@ -1090,7 +1090,7 @@ Main registration makes your provider discoverable by Prowler's core system. It' cis.batch_write_data_to_file() ``` -#### Step 11: Register in the list of providers +#### Step 11: Register in the List of Providers **Explanation:** This is needed to be able to use the provider in the generic checks. The provider must be registered in the `init_global_provider` method to handle CLI arguments and initialization. @@ -1966,7 +1966,7 @@ Main registration makes your provider discoverable by Prowler's core system. It' This step is the same as the [SDK providers](#step-10-register-in-main). -#### Step 11: Register in the list of providers +#### Step 11: Register in the List of Providers **Explanation:** This is needed to be able to use the provider in the generic checks. The provider must be registered in the `init_global_provider` method to handle CLI arguments and initialization. @@ -2648,7 +2648,7 @@ Main registration makes your provider discoverable by Prowler's core system. It' This step is the same as the [SDK providers](#step-10-register-in-main). -#### Step 7: Register in the list of providers +#### Step 7: Register in the List of Providers **Explanation:** This is needed to be able to use the provider in the generic checks. The provider must be registered in the `init_global_provider` method to handle CLI arguments and initialization. @@ -2808,7 +2808,7 @@ def validate_your_provider_uid(value): **Provider Model:** The `Provider` model already exists and supports all provider types. Ensure your provider type is included in the choices. -### 2.2. Add the provider to the Provider Choices +### 2.2. Add the Provider to the Provider Choices Update the `return_prowler_provider` function to include your provider. This function is crucial for the API to instantiate the correct provider class. @@ -3209,7 +3209,7 @@ class YourProviderAPITestCase(APITestCase): self.assertEqual(response.status_code, 201) ``` -#### 2.6.1. Add your mocked provider to the tests +#### 2.6.1. Add Your Mocked Provider to the Tests If needed, add a named provider fixture or extend the provider factory defaults so tests can request only the provider they need. @@ -3272,7 +3272,7 @@ Your provider will be available through these endpoints: - `DELETE /api/v1/providers/{id}/` - Delete provider - `POST /api/v1/providers/secrets/` - Add provider credentials -### 2.9. Update the provider if needed +### 2.9. Update the Provider If Needed Depending on your provider's authentication requirements, you may need to add new authentication methods that are compatible with the API. This involves updating the provider class to support additional credential types beyond the basic ones. diff --git a/docs/developer-guide/security-compliance-framework.mdx b/docs/developer-guide/security-compliance-framework.mdx index 46d8d2722e..3dc84dc58c 100644 --- a/docs/developer-guide/security-compliance-framework.mdx +++ b/docs/developer-guide/security-compliance-framework.mdx @@ -18,7 +18,7 @@ A compliance framework must represent the **complete state** of the source catal Requirement coverage feeds the compliance percentage calculations and the metadata surfaces (dashboards, widgets, exports). Missing requirements skew those metrics and break the report as a faithful snapshot of the framework. -### Two supported schemas +### Two Supported Schemas | Schema | When to use | File location | Discovered as | | --- | --- | --- | --- | @@ -45,7 +45,7 @@ Before adding a new framework, complete the following checks: ## Universal Compliance Framework -### Where the file lives +### Where the File Lives Place the file at the top level of the compliance directory: @@ -57,7 +57,7 @@ Examples in the repository: `prowler/compliance/csa_ccm_4.0.json`, `prowler/comp The file is auto-discovered — there is **no** need to register it in any `__init__.py`, modify `prowler/lib/outputs/`, or update any other Python module. The framework key Prowler CLI accepts via `--compliance` is the basename of the JSON file without `.json` (`dora_2022_2554.json` → `dora_2022_2554`). -### Top-level structure +### Top-Level Structure ```json { @@ -198,7 +198,7 @@ Per requirement: For MITRE-style frameworks, additional optional fields are available on the requirement: `tactics`, `sub_techniques`, `platforms`, `technique_url` (these are populated automatically when adapting a legacy MITRE JSON to the universal model). -### Multi-provider frameworks +### Multi-Provider Frameworks A single universal file can cover any number of providers. The framework appears under each provider's `--list-compliance` output as long as **at least one** requirement has that provider key in its `checks` dict. @@ -226,7 +226,7 @@ The legacy schema spans **four layers** — a complete contribution must touch e The universal schema collapses Layers 3 and 4 into declarative configuration inside the JSON — that is the main reason it is preferred for new contributions. -### Directory structure and file naming +### Directory Structure and File Naming Compliance frameworks live at: @@ -259,7 +259,7 @@ prowler/lib/outputs/compliance// └── __init__.py ``` -### JSON schema reference +### JSON Schema Reference Every legacy compliance file is a JSON document with the following top-level keys. `Framework`, `Name` and `Provider` are validated non-empty by the root validator `framework_and_provider_must_not_be_empty` (`compliance_models.py`). @@ -362,7 +362,7 @@ For the remaining attribute classes (`AWS_Well_Architected_Requirement_Attribute The `Attributes` field is a Pydantic `Union`. The generic attribute model **must** remain the last element of that Union — otherwise Pydantic v1 silently coerces every framework into the generic shape and your specialized fields are dropped. Adding a brand-new attribute shape requires inserting the Pydantic class **before** `Generic_Compliance_Requirement_Attribute`. -#### Minimal working example +#### Minimal Working Example The following snippet is a complete, valid framework file named `my_framework_1.0_aws.json`, saved at `prowler/compliance/aws/my_framework_1.0_aws.json`. It uses the generic attribute shape for simplicity. @@ -408,7 +408,7 @@ The following snippet is a complete, valid framework file named `my_framework_1. } ``` -### Mapping checks to requirements +### Mapping Checks to Requirements Each requirement links to the Prowler checks that, together, produce a PASS or FAIL verdict for that control. @@ -425,7 +425,7 @@ To discover available checks: uv run python prowler-cli.py --list-checks ``` -### Supporting multiple providers (legacy) +### Supporting Multiple Providers (Legacy) The legacy schema binds each file to a single provider. To cover several providers with the same framework, ship one JSON file per provider: @@ -439,7 +439,7 @@ Keep the `Framework` and `Version` values identical across the files so the disp For a brand-new framework that spans several providers, **prefer the universal schema** — it covers every provider from a single file. If you must use the legacy schema, add one transformer per provider in `prowler/lib/outputs/compliance//` and extend the summary-table dispatcher accordingly. See [Output Formatter](#output-formatter). -### Output formatter +### Output Formatter Legacy frameworks render in two forms: a detailed CSV report written to disk, and a summary table printed in the CLI. Both are produced by the output formatter package for the framework. Universal frameworks do **not** need a Python output formatter — the `outputs` config inside the JSON drives rendering — so this section applies only to the legacy schema. @@ -453,19 +453,19 @@ prowler/lib/outputs/compliance/my_framework/ └── models.py # CSV row Pydantic model ``` -#### Step 1 — Define the CSV row model +#### Step 1 — Define the CSV Row Model In `models.py`, declare a Pydantic v1 model with one field per CSV column. Use existing models such as `AWSCISModel` in `prowler/lib/outputs/compliance/cis/models.py` as the reference. Fields typically include `Provider`, `Description`, `AccountId`, `Region`, `AssessmentDate`, `Requirements_Id`, `Requirements_Description`, one `Requirements_Attributes_*` field per attribute key, plus the finding fields `Status`, `StatusExtended`, `ResourceId`, `ResourceName`, `CheckId`, `Muted`, `Framework`, `Name`. -#### Step 2 — Implement the transformer +#### Step 2 — Implement the Transformer In `my_framework_aws.py`, subclass `ComplianceOutput` from `prowler.lib.outputs.compliance.compliance_output` and implement `transform(findings, compliance, compliance_name)`. Iterate over `findings`, match each finding to the requirements it satisfies through `finding.compliance.get(compliance_name, [])`, and append one row per attribute to `self._data`. -#### Step 3 — Add the summary-table dispatcher +#### Step 3 — Add the Summary-Table Dispatcher In `my_framework.py`, implement `get_my_framework_table(findings, bulk_checks_metadata, compliance_framework, output_filename, output_directory, compliance_overview)` following the pattern in `prowler/lib/outputs/compliance/cis/cis.py`. -#### Step 4 — Register the framework in the dispatchers +#### Step 4 — Register the Framework in the Dispatchers - Add the dispatcher call in `prowler/lib/outputs/compliance/compliance.py`, inside `display_compliance_table`, with a branch such as `elif "my_framework" in compliance_framework:`. - Register the CSV model and transformer in `prowler/lib/outputs/compliance/compliance_output.py` so the CSV file is emitted during the scan. @@ -474,7 +474,7 @@ In `my_framework.py`, implement `get_my_framework_table(findings, bulk_checks_me For NIST-style catalogs that use `Generic_Compliance_Requirement_Attribute`, no custom formatter is needed. The generic formatter in `prowler/lib/outputs/compliance/generic/` handles them automatically, provided the JSON validates against the generic attribute schema. -### Legacy-to-universal adapter +### Legacy-to-Universal Adapter At load time, every legacy file is transparently adapted to a `ComplianceFramework` via `adapt_legacy_to_universal()` (`compliance_models.py`), which: (a) flattens the first element of `Attributes` into a flat `attributes` dict, (b) wraps `Checks` as `{provider_lower: [...]}`, (c) infers `attributes_metadata` from the matched Pydantic class via `_infer_attribute_metadata()`. The rest of Prowler (CSV/OCSF/PDF output, CLI table) then treats both formats identically. @@ -497,7 +497,7 @@ Configuration guardrails close that gap. A requirement declares the configuratio Guardrails are an **optional** safety net for configurable checks. A requirement that maps only to non-configurable checks does not need them. When the field is absent, behavior is unchanged. -### Where guardrails are declared +### Where Guardrails Are Declared The field is attached to each requirement and exists in both schemas: @@ -506,7 +506,7 @@ The field is attached to each requirement and exists in both schemas: When a legacy file is adapted to the universal model, `adapt_legacy_to_universal()` copies `ConfigRequirements` into `config_requirements` (`compliance_models.py`), so downstream code only ever reads one shape. -### Constraint schema +### Constraint Schema Each entry in the list is a single constraint with the following fields: @@ -533,7 +533,7 @@ Each entry in the list is a single constraint with the following fields: `subset` / `superset` require both the applied value and `Value` to be lists; any other type is treated as not satisfied. For `eq` against a boolean, declare `Value` as a JSON boolean (`false`, not `0`) — the model keeps booleans distinct from integers. -### How guardrails are evaluated +### How Guardrails Are Evaluated All evaluation lives in one shared module, `prowler/lib/check/compliance_config_eval.py`, consumed by every compliance output (CSV, OCSF, and the CLI tables) and reused by the Prowler API backend so the rule is defined exactly once. @@ -547,7 +547,7 @@ All evaluation lives in one shared module, `prowler/lib/check/compliance_config_ Guardrails only ever make a result **stricter** (they can turn PASS into FAIL); they never relax a real FAIL into PASS. A requirement with no constraints, or whose keys all use defaults, is reported exactly as before. -### Example: legacy framework +### Example: Legacy Framework From `prowler/compliance/aws/cis_6.0_aws.json`, requirement 2.11 declares two guardrails — one per configurable check it maps to: @@ -590,7 +590,7 @@ A boolean guardrail from the same file: requirement 2.5 (IAM Access Analyzer) on ] ``` -### Example: universal framework +### Example: Universal Framework The universal schema uses the lowercase `config_requirements` key with the identical object shape: @@ -616,7 +616,7 @@ The universal schema uses the lowercase `config_requirements` key with the ident Each constraint declares the `Provider` it targets so the guardrail is only evaluated on scans of that provider — essential for universal frameworks like CSA CCM and DORA, where one requirement maps checks across `aws`, `azure`, `gcp` and more. Because the operator is `subset`, adding `"TLS 1.0"` to `recommended_minimal_tls_versions` widens the allowlist beyond `["TLS 1.2", "TLS 1.3"]` and the requirement is forced to FAIL. -### What the user sees +### What the User Sees With a loosened config, the affected requirement's findings report: @@ -630,7 +630,7 @@ StatusExtended: Configuration not valid for this requirement. The check The same `Configuration not valid for this requirement.` message appears identically across the CSV, OCSF, and console-table outputs. -### Authoring guidelines +### Authoring Guidelines - Declare a guardrail only for keys whose value actually changes whether the requirement is met. Most configurable checks do not need one. - Set `Value` to the **strictest** configuration the control tolerates — the same number the control text cites (CIS 45 days, NIST ≤90, and so on). @@ -639,7 +639,7 @@ The same `Configuration not valid for this requirement.` message appears identic - Pick the operator from the value's role: a max threshold is `lte`, a min threshold is `gte`, a toggle is `eq`, an allowlist is `subset`, a denylist is `superset`. - An unrecognized operator does **not** block the requirement — a malformed constraint is treated as satisfied rather than failing the whole framework. Validate your JSON with the tests below. -### Testing guardrails +### Testing Guardrails The shared evaluator and the per-output integration are covered by: @@ -670,7 +670,7 @@ Prowler matches frameworks by concatenating `Framework` and `Version`. A missing Before opening a PR, validate the JSON loads cleanly against the model and that every referenced check actually exists. -### 1. Schema validation +### 1. Schema Validation For **universal** frameworks, load the file and inspect what was parsed. The framework key inside `bulk` is the **basename of the JSON file** (without `.json`); for `prowler/compliance/dora_2022_2554.json` that key is `dora_2022_2554`, for `prowler/compliance/aws/cis_5.0_aws.json` it is `cis_5.0_aws`. @@ -688,7 +688,7 @@ bulk = get_bulk_compliance_frameworks_universal("aws") assert "" in bulk ``` -### 2. Check existence cross-check +### 2. Check Existence Cross-Check There is **no automatic check-existence validation** at load time. Cross-check that every check name in your framework maps to a real check directory: @@ -708,7 +708,7 @@ missing = referenced - real assert not missing, f"checks referenced in framework but not found in repo: {sorted(missing)}" ``` -### 3. CLI smoke test +### 3. CLI Smoke Test ```bash uv run python prowler-cli.py --list-compliance @@ -728,7 +728,7 @@ Verify that: - The CLI summary table lists every section / pillar of the framework. - Findings roll up under the expected requirements. -### 4. Inspect the CSV output +### 4. Inspect the CSV Output Open the generated CSV and confirm: diff --git a/docs/developer-guide/server-sent-events.mdx b/docs/developer-guide/server-sent-events.mdx index c91f27227f..6fb9c7a00e 100644 --- a/docs/developer-guide/server-sent-events.mdx +++ b/docs/developer-guide/server-sent-events.mdx @@ -12,7 +12,7 @@ This guide explains how to add a **Server-Sent Events (SSE)** endpoint to the Pr The platform ships the SSE **infrastructure** (`api.sse`) and wiring. No feature endpoint streams over SSE out of the box — this guide shows how to build one on top of the shared base. -## When to use SSE +## When to Use SSE | Need | Use | |------|-----| @@ -22,7 +22,7 @@ The platform ships the SSE **infrastructure** (`api.sse`) and wiring. No feature SSE is the right tool when the **client only consumes**: scan progress, long-running job checkpoints, streamed LLM tokens, cross-client resource-sync notifications. It rides on plain HTTP, reconnects automatically in the browser via the native [`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) API, and needs no extra protocol. -## How it works +## How It Works SSE is wired through [`django-eventstream`](https://github.com/fanout/django_eventstream) and a small platform layer in `api/src/backend/api/sse/`: @@ -34,11 +34,11 @@ SSE is wired through [`django-eventstream`](https://github.com/fanout/django_eve | `make_channel_name` / `tenant_id_from_channel` | `api/sse/utils.py` | Single source of truth for the channel-name format, so publishers and the channel manager agree byte-for-byte. | | Settings | `config/settings/eventstream.py` | Valkey Pub/Sub backend (dedicated DB), channel manager, allowed headers. | -### Transport: the server runs on ASGI +### Transport: The Server Runs on ASGI SSE connections are long-lived. Holding one open per synchronous worker would exhaust the worker pool, so the API runs under Gunicorn's native **`asgi` worker** (`config.asgi:application`). Streams are parked on the event loop while ordinary CRUD endpoints keep their synchronous execution (Django runs sync views in a thread-sensitive executor under ASGI). This is configured in `config/guniconf.py` and used by both the dev and production entrypoints — no separate server process is needed. -### The data flow +### The Data Flow ``` publisher (Celery task / view) subscriber (browser, CLI) @@ -53,7 +53,7 @@ publisher (Celery task / view) subscriber (browser, CLI) A publisher anywhere in the system (most often a Celery task) calls `send_event(channel, event_type, payload)`. `django-eventstream` fans it out over Valkey Pub/Sub to every connection subscribed to that channel. -## Adding an SSE endpoint to your feature +## Adding an SSE Endpoint to Your Feature The example below streams progress for a long-running **scan**. Adapt the resource, prefix, and event names to your feature. @@ -161,7 +161,7 @@ publish_end(channel, scan_id=str(scan.id)) -## Event naming convention +## Event Naming Convention Every event uses an event type of the form **`.`** (lowercased, dot-separated). The verb comes from this platform-wide vocabulary — if you need a verb that is not listed, document the addition in this guide so the catalog stays discoverable. @@ -197,7 +197,7 @@ curl -N -H "Authorization: Bearer $JWT" \ https:///api/v1/scans/$SCAN_ID/event-stream ``` -## Tenant isolation & security model +## Tenant Isolation & Security Model Authorization is enforced at two layers: @@ -206,7 +206,7 @@ Authorization is enforced at two layers: Because the tenant id lives inside the channel name, this gate works for any feature without the platform knowing anything about it. -## Reconnect & state recovery +## Reconnect & State Recovery The platform deliberately ships **without server-side replay** (`is_channel_reliable` returns `False`). When a client reconnects, it does **not** receive missed events. Instead: @@ -215,7 +215,7 @@ The platform deliberately ships **without server-side replay** (`is_channel_reli Design your event payloads accordingly: deltas are ephemeral and concatenated in-flight; the durable truth always lives behind a REST resource. -## Local development +## Local Development - The dev and production entrypoints both launch Gunicorn with the `asgi` worker (`config.asgi:application`). In dev, `DJANGO_DEBUG=True` enables hot reload; `preload_app` is automatically disabled under debug so edited code is picked up. - SSE uses a **dedicated Valkey database** (`EVENTSTREAM_VALKEY_DB`, default `2`) kept separate from the Celery broker so a noisy broker cannot crowd out streaming traffic. It reuses the same `VALKEY_*` connection settings as the rest of the platform. diff --git a/docs/getting-started/products/prowler-mcp.mdx b/docs/getting-started/products/prowler-mcp.mdx index 3deb88489c..24520ed739 100644 --- a/docs/getting-started/products/prowler-mcp.mdx +++ b/docs/getting-started/products/prowler-mcp.mdx @@ -161,7 +161,7 @@ The Prowler MCP Server enables powerful workflows through AI assistants: - "What authentication methods does Prowler support for Azure?" - "How can I contribute with a new security check to Prowler?" -### Example: Creating a custom dashboard with Prowler extracted data +### Example: Creating a Custom Dashboard with Prowler Extracted Data In the next example you can see how to create a dashboard using Prowler MCP Server and Claude Desktop. diff --git a/docs/troubleshooting.mdx b/docs/troubleshooting.mdx index 9e0c849796..8b23550c4b 100644 --- a/docs/troubleshooting.mdx +++ b/docs/troubleshooting.mdx @@ -22,7 +22,7 @@ See section [Logging](/user-guide/cli/tutorials/logging) for further information Common issues with the Docker Compose installation of Prowler Local Server. -### Problem adding AWS Provider using "Connect assuming IAM Role" in Docker +### Problem Adding AWS Provider Using "Connect assuming IAM Role" in Docker See [GitHub Issue #7745](https://github.com/prowler-cloud/prowler/issues/7745) for more details. diff --git a/docs/user-guide/cli/tutorials/fixer.mdx b/docs/user-guide/cli/tutorials/fixer.mdx index 4170b340e2..f777d64713 100644 --- a/docs/user-guide/cli/tutorials/fixer.mdx +++ b/docs/user-guide/cli/tutorials/fixer.mdx @@ -105,7 +105,7 @@ def fixer(resource_id: str) -> bool: return True ``` -## Fixer Config file +## Fixer Config File For some fixers, you can have configurable parameters depending on your use case. You can either use the default config file in `prowler/config/fixer_config.yaml` or create a custom config file and pass it to the fixer with the `--fixer-config` flag. The config file should be a YAML file with the following structure: diff --git a/docs/user-guide/cli/tutorials/misc.mdx b/docs/user-guide/cli/tutorials/misc.mdx index 0940508ed7..59f34c3660 100644 --- a/docs/user-guide/cli/tutorials/misc.mdx +++ b/docs/user-guide/cli/tutorials/misc.mdx @@ -4,7 +4,7 @@ title: 'Miscellaneous' ## Prowler Version -### Showing the Prowler version: +### Showing the Prowler Version ```console prowler -V/-v/--version @@ -22,7 +22,7 @@ To enable verbose mode in Prowler, similar to Version 2, use: prowler --verbose ``` -### Filter findings by status +### Filter Findings by Status Prowler allows filtering findings based on their status, ensuring reports and CLI display only relevant findings: diff --git a/docs/user-guide/cli/tutorials/mutelist.mdx b/docs/user-guide/cli/tutorials/mutelist.mdx index 77b710d3df..b11a41f1c9 100644 --- a/docs/user-guide/cli/tutorials/mutelist.mdx +++ b/docs/user-guide/cli/tutorials/mutelist.mdx @@ -268,7 +268,7 @@ Accounts: ## AWS Mutelist -### Muting specific AWS regions +### Muting Specific AWS Regions If you want to mute failed findings only in specific regions, create a file with the following syntax and run it with `prowler aws -w mutelist.yaml`: diff --git a/docs/user-guide/providers/alibabacloud/getting-started-alibabacloud.mdx b/docs/user-guide/providers/alibabacloud/getting-started-alibabacloud.mdx index ce9778a3b5..e887ead21e 100644 --- a/docs/user-guide/providers/alibabacloud/getting-started-alibabacloud.mdx +++ b/docs/user-guide/providers/alibabacloud/getting-started-alibabacloud.mdx @@ -144,25 +144,25 @@ prowler alibabacloud --ecs-ram-role RoleName ### Step 2: Run the First Scan -#### Scan all regions +#### Scan All Regions ```bash prowler alibabacloud ``` -#### Scan specific regions +#### Scan Specific Regions ```bash prowler alibabacloud --region cn-hangzhou cn-shanghai ``` -#### Run specific checks +#### Run Specific Checks ```bash prowler alibabacloud --checks ram_no_root_access_key ram_user_mfa_enabled_console_access ``` -#### Run a compliance framework +#### Run a Compliance Framework ```bash prowler alibabacloud --compliance cis_2.0_alibabacloud diff --git a/docs/user-guide/providers/aws/organizations.mdx b/docs/user-guide/providers/aws/organizations.mdx index 92a4faf2ae..9729a86a26 100644 --- a/docs/user-guide/providers/aws/organizations.mdx +++ b/docs/user-guide/providers/aws/organizations.mdx @@ -167,7 +167,7 @@ Include the `ExternalId` parameter in the StackSet if required by the organizati When encountering issues during deployment or needing to target specific OUs or environments (e.g., dev/staging/prod), reach out to the Prowler team via [Slack Community](https://prowler.com/slack) or [Support](mailto:support@prowler.com). -## Extra: Run Prowler across all accounts in AWS Organizations by assuming roles +## Extra: Run Prowler Across All Accounts in AWS Organizations by Assuming Roles ### Running Prowler Across All AWS Organization Accounts diff --git a/docs/user-guide/providers/mongodbatlas/getting-started-mongodbatlas.mdx b/docs/user-guide/providers/mongodbatlas/getting-started-mongodbatlas.mdx index 2fb415a11b..bf2c76447e 100644 --- a/docs/user-guide/providers/mongodbatlas/getting-started-mongodbatlas.mdx +++ b/docs/user-guide/providers/mongodbatlas/getting-started-mongodbatlas.mdx @@ -36,7 +36,7 @@ If **Require IP Access List for the Atlas Administration API** is enabled in the -### Step 1: Add the provider +### Step 1: Add the Provider 1. Navigate to **Providers** and click **Add Provider**. ![Add provider list](./img/add-provider-list.png) @@ -45,13 +45,13 @@ If **Require IP Access List for the Atlas Administration API** is enabled in the ![Add organization ID](./img/add-org-id.png) 4. (Optional) Add a friendly alias to identify this organization in dashboards. -### Step 2: Provide API credentials +### Step 2: Provide API Credentials 1. Click **Next** to open the credentials form. 2. Paste the **Atlas Public Key** and **Atlas Private Key** generated in the Atlas console. ![Add credentials](./img/add-credentials.png) -### Step 3: Test the connection and start scanning +### Step 3: Test the Connection and Start Scanning 1. Click **Test connection** to ensure Prowler Cloud can reach the Atlas API. 2. Save the credentials. The provider will appear in the list with its current connection status. @@ -66,11 +66,11 @@ If **Require IP Access List for the Atlas Administration API** is enabled in the You can also run MongoDB Atlas assessments directly from the CLI. Both command-line flags and environment variables are supported. -### Step 1: Select an authentication method +### Step 1: Select an Authentication Method Choose one of the following authentication methods: -#### Command-line arguments +#### Command-Line Arguments ```bash prowler mongodbatlas \ @@ -78,7 +78,7 @@ prowler mongodbatlas \ --atlas-private-key ``` -#### Environment variables +#### Environment Variables ```bash export ATLAS_PUBLIC_KEY= @@ -86,9 +86,9 @@ export ATLAS_PRIVATE_KEY= prowler mongodbatlas ``` -### Step 2: Run the first scan +### Step 2: Run the First Scan -#### Scan all projects and clusters +#### Scan All Projects and Clusters ```bash prowler mongodbatlas @@ -96,7 +96,7 @@ prowler mongodbatlas This command enumerates all projects accessible to the API key and scans every cluster. -#### Scan a specific project +#### Scan a Specific Project Add the `--atlas-project-id` flag when you only want to assess one project: @@ -104,7 +104,7 @@ Add the `--atlas-project-id` flag when you only want to assess one project: prowler mongodbatlas --atlas-project-id ``` -### Additional tips +### Additional Tips - Combine flags (for example, `--checks` or `--services`) just like with other providers. - Use `--output-modes` to export findings in JSON, CSV, ASFF, etc. diff --git a/docs/user-guide/providers/okta/authentication.mdx b/docs/user-guide/providers/okta/authentication.mdx index 8f664160a2..059667ee09 100644 --- a/docs/user-guide/providers/okta/authentication.mdx +++ b/docs/user-guide/providers/okta/authentication.mdx @@ -67,7 +67,7 @@ The service application must be assigned **one** of the following Okta admin rol Okta's Management API enforces a two-layer authorization model: an OAuth **scope** decides which API endpoints the token can call, and an **admin role** decides whether the call returns data. With only a scope granted, the token mint succeeds but every read returns `403 Forbidden`. Read-Only Administrator is the minimum role that lets the granted `okta.*.read` scopes return configuration data to Prowler's checks; without it, the credential probe at provider startup fails and the scan never gets to evaluate any check. -#### When Super Administrator is required +#### When Super Administrator Is Required Four checks need to resolve the Authentication Policy bound to Okta's first-party apps (Okta Admin Console, Okta Dashboard) and depend on `/api/v1/apps` returning those system apps — which Okta restricts to Super Administrator: @@ -92,17 +92,17 @@ Read-Only Administrator stays the recommended default for the least-privilege fr ## Step-by-Step Setup -### 1. Go to the admin console +### 1. Go to the Admin Console ![Okta — admin console page](/user-guide/providers/okta/images/select-admin-console.png) -### 2. [Optional] - Disable the privilege-escalation bypass (org-wide, one-time) +### 2. [Optional] - Disable the Privilege-Escalation Bypass (Org-Wide, One-Time) In the Okta Admin Console, go to **Settings → Account → Public client app admins** and ensure it is **off**. When enabled, every API Services app can be auto-assigned the Super Administrator role after scopes are granted, which would invalidate the read-only premise of this integration. ![Okta — disable Public client app admins](/user-guide/providers/okta/images/public-client-app-admins.png) -### 3. Create the API Services app +### 3. Create the API Services App 1. Go to **Applications → Applications**. @@ -118,7 +118,7 @@ In the Okta Admin Console, go to **Settings → Account → Public client app ad ![Okta — copy client id](/user-guide/providers/okta/images/copy-client-id.png) -### 4. Switch to private-key authentication and generate a keypair +### 4. Switch to Private-Key Authentication and Generate a Keypair On the new app's **General** tab, scroll to **Client Credentials**: @@ -136,13 +136,13 @@ Okta displays the private key **only once**. If you close the modal without copy ![Okta — create Public Key](/user-guide/providers/okta/images/create-public-key.png) -### 5. Grant the required OAuth scopes +### 5. Grant the Required OAuth Scopes On the app, open the **Okta API Scopes** tab and click **Grant** on every scope Prowler needs. The bundled checks require `okta.policies.read`, `okta.brands.read`, `okta.apps.read`, `okta.authenticators.read`, `okta.networkZones.read`, `okta.apiTokens.read`, `okta.roles.read`, `okta.groups.read`, `okta.logStreams.read`, and `okta.idps.read`. ![Okta — grant OAuth scopes](/user-guide/providers/okta/images/grant-permissions.png) -### 6. Assign an admin role +### 6. Assign an Admin Role On the app, open the **Admin roles** tab and click **Edit assignments → Add assignment**: @@ -155,7 +155,7 @@ To additionally evaluate the first-party application checks (Okta Admin Console ![Okta — grant Read-Only role](/user-guide/providers/okta/images/grant-roles.png) -### 7. [Optional] Verify DPoP setting +### 7. [Optional] Verify DPoP Setting Prowler sends DPoP (Demonstrating Proof of Possession) proofs on every token request. The integration works whether the **Require Demonstrating Proof of Possession (DPoP) header in token requests** setting on the service app is on or off — but enabling it is the more secure default. @@ -206,20 +206,20 @@ The org domain must be `.okta.com` (or `.oktapreview.com` / `.okta-emea.com The file at `OKTA_PRIVATE_KEY_FILE` is missing, unreadable, or empty. Confirm the path and that the file contains a non-empty PEM block or JWK JSON document. -### `OktaInvalidCredentialsError` at provider init +### `OktaInvalidCredentialsError` at Provider Init Prowler validates credentials at startup by listing one sign-on policy. This error indicates the credential material itself was rejected: - **`invalid_client`** — the public key registered in Okta does not match the private key on disk. Generate a fresh keypair and try again. -### `OktaInsufficientPermissionsError` at provider init +### `OktaInsufficientPermissionsError` at Provider Init Raised when the credential probe succeeds at the OAuth layer but the request is rejected because the service app lacks the required scope or admin role: - **`invalid_scope`** — one of the requested scopes (`okta.policies.read`, `okta.brands.read`, `okta.apps.read`, `okta.authenticators.read`, `okta.networkZones.read`, `okta.apiTokens.read`, `okta.roles.read`, `okta.groups.read`, `okta.logStreams.read`, and `okta.idps.read`) is not granted on the service app. Grant the missing scope from **Okta API Scopes**. - **`Forbidden` / `not authorized`** — no admin role is assigned to the service app. Assign **Read-Only Administrator** (or **Super Administrator** for the first-party application checks) from **Admin roles**. -### Application-service checks return MANUAL on first-party apps +### Application-Service Checks Return MANUAL on First-Party Apps When the service app runs with Read-Only Administrator, the five application-service checks targeting the Okta Admin Console and Okta Dashboard return MANUAL. This is by design — Okta restricts the underlying endpoints (`/api/v1/first-party-app-settings/{appName}` and `/api/v1/apps` for first-party app `name` values `saasure` / `okta_enduser`) to **Super Administrator**. Assign the Super Administrator role to the service app to evaluate those checks. See [Required Admin Role](#required-admin-role) for the full list. diff --git a/docs/user-guide/tutorials/prowler-app-findings-triage.mdx b/docs/user-guide/tutorials/prowler-app-findings-triage.mdx index 408f201645..ce6632dd66 100644 --- a/docs/user-guide/tutorials/prowler-app-findings-triage.mdx +++ b/docs/user-guide/tutorials/prowler-app-findings-triage.mdx @@ -141,18 +141,18 @@ Muting a finding does not fix the underlying configuration. Review the finding b ## Troubleshooting -### Triage controls do not appear +### Triage Controls Do Not Appear Make sure the row is an individual finding row. Finding Groups rows do not show triage controls. Expand a group to see affected resources and their triage controls. -### Changes cannot be saved +### Changes Cannot Be Saved Confirm that the user role has **Manage Scans** permission. Prowler Local Server does not support Findings Triage writes. -### Resolved or Reopened is missing from the selector +### Resolved or Reopened Is Missing from the Selector **Reopened** is always automatic. **Resolved** is set automatically from scan result changes and appears as a selector option only on `MANUAL` findings, where it records a [Manual Pass](#verify-a-manual-finding-as-pass). On findings with any other status, this is expected. -### Risk Accepted or False Positive muted a finding +### Risk Accepted or False Positive Muted a Finding This is expected. Those statuses create a mute rule through Mutelist. diff --git a/docs/user-guide/tutorials/prowler-app-github-action.mdx b/docs/user-guide/tutorials/prowler-app-github-action.mdx index c874a37164..faf0993e21 100644 --- a/docs/user-guide/tutorials/prowler-app-github-action.mdx +++ b/docs/user-guide/tutorials/prowler-app-github-action.mdx @@ -28,7 +28,7 @@ Source: [`prowler-cloud/prowler`](https://github.com/prowler-cloud/prowler) · M ## Usage -### AWS scan +### AWS Scan ```yaml - uses: prowler-cloud/prowler@5.25 @@ -41,7 +41,7 @@ Source: [`prowler-cloud/prowler`](https://github.com/prowler-cloud/prowler) · M AWS_SESSION_TOKEN: ${{ secrets.AWS_SESSION_TOKEN }} ``` -### Push findings to Prowler Cloud +### Push Findings to Prowler Cloud Send scan results directly to [Prowler Cloud](/user-guide/tutorials/prowler-import-findings) for centralized visibility, compliance tracking, and team collaboration. @@ -97,7 +97,7 @@ jobs: - GitHub Code Scanning is free for public repositories. Private repositories require a [GitHub Code Security](https://docs.github.com/en/get-started/learning-about-github/about-github-advanced-security) license. -### Combine push-to-cloud with SARIF upload +### Combine Push-to-Cloud with SARIF Upload ```yaml - uses: prowler-cloud/prowler@5.25 @@ -114,7 +114,7 @@ jobs: PROWLER_CLOUD_API_KEY: ${{ secrets.PROWLER_CLOUD_API_KEY }} ``` -### Scan the current repository with the GitHub provider +### Scan the Current Repository with the GitHub Provider ```yaml name: Prowler GitHub Scan @@ -142,7 +142,7 @@ jobs: `--repository` scans a single repo. Use `--organization ` instead to include org-level checks (MFA, security policies, etc.). See the [GitHub provider authentication](/user-guide/providers/github/authentication) for required token permissions. -### Fail the PR on findings +### Fail the PR on Findings By default the action tolerates findings (exit code 3) and succeeds. Set `fail-on-findings: true` to fail the workflow step when Prowler detects findings. Combine with `--severity` to control which severity levels trigger the failure: @@ -258,7 +258,7 @@ Scan results are written to `output/` in the workspace and uploaded as artifacts When `upload-sarif` is enabled, SARIF results are also uploaded to GitHub Code Scanning and appear on the repository's **Security → Code scanning** tab, filtered by the branch that ran the scan. -### Step summary +### Step Summary The action writes a summary to the run page with a per-severity breakdown of failing checks, artifact and Code Scanning links, and (when `push-to-cloud: false`) a pointer to [Prowler Cloud](https://cloud.prowler.com) for continuous monitoring. diff --git a/docs/user-guide/tutorials/prowler-app-jira-integration.mdx b/docs/user-guide/tutorials/prowler-app-jira-integration.mdx index 3621fd514c..27832352f5 100644 --- a/docs/user-guide/tutorials/prowler-app-jira-integration.mdx +++ b/docs/user-guide/tutorials/prowler-app-jira-integration.mdx @@ -159,13 +159,13 @@ Support for custom field mapping is planned for a future release. ## Troubleshooting -### Connection test fails +### Connection Test Fails * Verify Jira instance domain is correct and accessible * Confirm API token or credentials are valid * Ensure API access is enabled in Jira settings and the needed scopes are granted -### Check task status (API) +### Check Task Status (API) If the Jira issue does not appear in your Jira project, follow these steps to verify the export task status via the API. diff --git a/docs/user-guide/tutorials/prowler-app-rbac.mdx b/docs/user-guide/tutorials/prowler-app-rbac.mdx index 90ecafbcb4..f00a852f19 100644 --- a/docs/user-guide/tutorials/prowler-app-rbac.mdx +++ b/docs/user-guide/tutorials/prowler-app-rbac.mdx @@ -257,7 +257,7 @@ The **Scope** column indicates where each permission applies. **All** means the To grant all administrative permissions, select the **Grant all admin permissions** option. -### Prowler Cloud exclusive permissions +### Prowler Cloud Exclusive Permissions The following permissions are available exclusively in **Prowler Cloud**: diff --git a/docs/user-guide/tutorials/prowler-import-findings.mdx b/docs/user-guide/tutorials/prowler-import-findings.mdx index f32863b90b..0a55878988 100644 --- a/docs/user-guide/tutorials/prowler-import-findings.mdx +++ b/docs/user-guide/tutorials/prowler-import-findings.mdx @@ -444,7 +444,7 @@ For pricing details, see [Prowler Cloud Pricing](https://prowler.com/pricing). - The user associated with the API key lacks the **Manage Ingestions** permission - Contact the tenant administrator to grant the required permission -### Ingestion job status is "failed" +### Ingestion Job Status Is "failed" - Check the `/api/v1/ingestions/{id}/errors` endpoint for details - Verify the OCSF file format is valid From 73d5c6952b9485e654937ae7aaf1ace783040a67 Mon Sep 17 00:00:00 2001 From: "mintlify[bot]" <109931778+mintlify[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 09:18:08 +0200 Subject: [PATCH 02/77] docs: fix typos and grammar (#12672) Co-authored-by: mintlify[bot] <109931778+mintlify[bot]@users.noreply.github.com> --- docs/changelog.mdx | 2 +- docs/developer-guide/aws-details.mdx | 4 ++-- docs/developer-guide/debugging.mdx | 2 +- docs/developer-guide/end2end-testing.mdx | 6 +++--- docs/developer-guide/services.mdx | 2 +- docs/developer-guide/unit-testing.mdx | 8 ++++---- docs/getting-started/basic-usage/prowler-cli.mdx | 2 +- docs/user-guide/cli/tutorials/pentesting.mdx | 5 +---- docs/user-guide/tutorials/prowler-app.mdx | 2 +- 9 files changed, 15 insertions(+), 18 deletions(-) diff --git a/docs/changelog.mdx b/docs/changelog.mdx index ebde6f419e..68e93b9a94 100644 --- a/docs/changelog.mdx +++ b/docs/changelog.mdx @@ -409,7 +409,7 @@ rss: true All checks are fully passive, using AWS APIs and CloudTrail with no instance access or SSM agent required, and are mapped across 23 compliance frameworks, including NIST 800-53 Rev 5, PCI-DSS v4.0, ISO 27001:2022, SOC 2, HIPAA, and MITRE ATT&CK. - Read more about it this [blog post](https://prowler.com/blog/your-llm-runs-in-a-nitro-enclave-who-is-checking-the-enclave). + Read more about it in this [blog post](https://prowler.com/blog/your-llm-runs-in-a-nitro-enclave-who-is-checking-the-enclave). Try them out now at [cloud.prowler.com](https://cloud.prowler.com/sign-up)! diff --git a/docs/developer-guide/aws-details.mdx b/docs/developer-guide/aws-details.mdx index ad24731b4f..a653148a4c 100644 --- a/docs/developer-guide/aws-details.mdx +++ b/docs/developer-guide/aws-details.mdx @@ -57,7 +57,7 @@ The AWS provider implementation follows the general [Provider structure](/develo The generic service pattern is described in [service page](/developer-guide/services#service-structure-and-initialisation). You can find all the right now implemented services in the following locations: - Directly in the code, in location [`prowler/providers/aws/services/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/aws/services) -- In the [Prowler Hub](https://hub.prowler.com/). For a more human-readable view. +- In the [Prowler Hub](https://hub.prowler.com/) for a more human-readable view. The best reference to understand how to implement a new service is following the [service implementation documentation](/developer-guide/services#adding-a-new-service) and taking other services already implemented as reference. In next subsection you can find a list of common patterns that are used across all AWS services. @@ -131,7 +131,7 @@ def _get_email_identities(self, identity): The AWS checks pattern is described in [checks page](/developer-guide/checks). You can find all the right now implemented checks: - Directly in the code, within each service folder, each check has its own folder named after the name of the check. (e.g. [`prowler/providers/aws/services/s3/s3_bucket_acl_prohibited/`](https://github.com/prowler-cloud/prowler/tree/master/prowler/providers/aws/services/s3/s3_bucket_acl_prohibited)) -- In the [Prowler Hub](https://hub.prowler.com/). For a more human-readable view. +- In the [Prowler Hub](https://hub.prowler.com/) for a more human-readable view. The best reference to understand how to implement a new check is following the [check creation documentation](/developer-guide/checks#creating-a-check) and taking other similar checks as reference. diff --git a/docs/developer-guide/debugging.mdx b/docs/developer-guide/debugging.mdx index 647b23c614..8bb6643eb7 100644 --- a/docs/developer-guide/debugging.mdx +++ b/docs/developer-guide/debugging.mdx @@ -10,7 +10,7 @@ Visual Studio Code (also referred to as VSCode) provides an integrated debugger ### Debugging Configuration Example -The following file is an example of a [debugging configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) file for [Virtual Studio Code](https://code.visualstudio.com/). +The following file is an example of a [debugging configuration](https://code.visualstudio.com/docs/editor/debugging#_launch-configurations) file for [Visual Studio Code](https://code.visualstudio.com/). This file must be placed inside the *.vscode* directory and named *launch.json*: diff --git a/docs/developer-guide/end2end-testing.mdx b/docs/developer-guide/end2end-testing.mdx index df99de6fee..f8b54af222 100644 --- a/docs/developer-guide/end2end-testing.mdx +++ b/docs/developer-guide/end2end-testing.mdx @@ -50,7 +50,7 @@ When adding or maintaining E2E tests for Prowler Local Server, follow these guid ``` 5. **Tag and document scenarios** - - Follow the existing naming convention for suites and test cases (for example, `SCANS-E2E-001`, `PROVIDER-E2E-003`) and use tags such as `@e2e`, `@serial` and feature tags (for example, `@providers`, `@scans`,`@aws`) to filter and organize tests. + - Follow the existing naming convention for suites and test cases (for example, `SCANS-E2E-001`, `PROVIDER-E2E-003`) and use tags such as `@e2e`, `@serial` and feature tags (for example, `@providers`, `@scans`, `@aws`) to filter and organize tests. **Example:** ```typescript @@ -71,7 +71,7 @@ When adding or maintaining E2E tests for Prowler Local Server, follow these guid } ); ``` - - Document each one in the Markdown files under `ui/tests`, including **Priority**, **Tags**, **Description**, **Preconditions**, **Flow steps**, **Expected results**,**Key verification points** and **Notes**. + - Document each one in the Markdown files under `ui/tests`, including **Priority**, **Tags**, **Description**, **Preconditions**, **Flow steps**, **Expected results**, **Key verification points** and **Notes**. **Example** ```Markdown @@ -256,7 +256,7 @@ To execute E2E tests for Prowler Local Server: pnpm run test:e2e ``` - This command runs Playwright with the configured projects + This command runs Playwright with the configured projects. 2. **Run E2E tests with the Playwright UI runner** diff --git a/docs/developer-guide/services.mdx b/docs/developer-guide/services.mdx index 775c0f52c7..beda2dcd56 100644 --- a/docs/developer-guide/services.mdx +++ b/docs/developer-guide/services.mdx @@ -537,7 +537,7 @@ This architecture allows Prowler to efficiently scan AWS accounts with resources ## Best Practices -- When available in the provider, use threading or parallelization utilities for all methods that can be parallelized by to maximize performance and reduce scan time. +- When available in the provider, use threading or parallelization utilities for all methods that can be parallelized to maximize performance and reduce scan time. - Define a Pydantic `BaseModel` for every resource you manage, and use these models for all resource data handling. - Log every major step (start, success, error) in resource discovery and attribute collection for traceability and debugging; include as much context as possible. - Catch and log all exceptions, providing detailed context (region, subscription, resource, error type, line number) to aid troubleshooting. diff --git a/docs/developer-guide/unit-testing.mdx b/docs/developer-guide/unit-testing.mdx index 8c8ba5ed49..0a07257b0b 100644 --- a/docs/developer-guide/unit-testing.mdx +++ b/docs/developer-guide/unit-testing.mdx @@ -154,7 +154,7 @@ Failing to update this table when adding cross-service dependencies may result i For AWS provider, different testing approaches apply based on API coverage based on several criteria. -Prowler leverages and contributes to the[Moto](https://github.com/getmoto/moto) library for mocking AWS infrastructure in tests. +Prowler leverages and contributes to the [Moto](https://github.com/getmoto/moto) library for mocking AWS infrastructure in tests. - AWS API Calls Covered by [Moto](https://github.com/getmoto/moto): @@ -408,7 +408,7 @@ In all above scenarios, check execution must occur within the context of mocked When a service requires API calls that are partially covered by the Moto decorator, additional mocking is necessary. In such cases, custom mocked API calls must be implemented alongside Moto to ensure full coverage. -To achieve this, mock the `botocore.client.BaseClient._make_api_call` function—the method responsible for making actual API requests to AWS—using `mock.patch `: +To achieve this, mock the `botocore.client.BaseClient._make_api_call` function—the method responsible for making actual API requests to AWS—using [`mock.patch`](https://docs.python.org/3/library/unittest.mock.html#patch): ```python @@ -475,7 +475,7 @@ However, if additional `moto` decorators are applied alongside the patch, Moto w -The source of the above implementation can be found here:[Patch Other Services with Moto](https://docs.getmoto.org/en/latest/docs/services/patching\_other\_services.html) +The source of the above implementation can be found here: [Patch Other Services with Moto](https://docs.getmoto.org/en/latest/docs/services/patching_other_services.html) #### Mocking Several Services @@ -603,7 +603,7 @@ with mock.patch( will cause that the service is initialized only once—at the moment of mocking out `set_mocked_aws_provider([])` using `mock.patch`. -Later, when Python attempts to import the client at the check level, the execution continues using`from prowler.providers..services.._client`. As a result of it being already mocked out, the execution will continue using `service_client` without getting into `_client.py`. +Later, when Python attempts to import the client at the check level, the execution continues using `from prowler.providers..services.._client`. As a result of it being already mocked out, the execution will continue using `service_client` without getting into `_client.py`. ### Testing AWS Services diff --git a/docs/getting-started/basic-usage/prowler-cli.mdx b/docs/getting-started/basic-usage/prowler-cli.mdx index 0efa1ce8f1..ebf3c6515e 100644 --- a/docs/getting-started/basic-usage/prowler-cli.mdx +++ b/docs/getting-started/basic-usage/prowler-cli.mdx @@ -4,7 +4,7 @@ title: 'Basic Usage' ## Running Prowler -Running Prowler requires specifying the provider (e.g `aws`, `gcp`, `azure`, `kubernetes`, `m365`, `github`, `iac` or `mongodbatlas`): +Running Prowler requires specifying the provider (e.g. `aws`, `gcp`, `azure`, `kubernetes`, `m365`, `github`, `iac` or `mongodbatlas`): If no provider is specified, AWS is used by default for backward compatibility with Prowler v2. diff --git a/docs/user-guide/cli/tutorials/pentesting.mdx b/docs/user-guide/cli/tutorials/pentesting.mdx index a9a8c728df..0d7be461d7 100644 --- a/docs/user-guide/cli/tutorials/pentesting.mdx +++ b/docs/user-guide/cli/tutorials/pentesting.mdx @@ -43,8 +43,7 @@ prowler --categories secrets Several checks analyse resources that are exposed to the Internet, these are: -1. apigateway\_restapi\_public - +- apigateway\_restapi\_public - appstream\_fleet\_default\_internet\_access\_disabled - awslambda\_function\_not\_publicly\_accessible - ec2\_ami\_public @@ -58,8 +57,6 @@ Several checks analyse resources that are exposed to the Internet, these are: - ecr\_repositories\_not\_publicly\_accessible - eks\_control\_plane\_endpoint\_access\_restricted - eks\_endpoints\_not\_publicly\_accessible -- eks\_control\_plane\_endpoint\_access\_restricted -- eks\_endpoints\_not\_publicly\_accessible - elbv2\_internet\_facing - kms\_key\_not\_publicly\_accessible - opensearch\_service\_domains\_not\_publicly\_accessible diff --git a/docs/user-guide/tutorials/prowler-app.mdx b/docs/user-guide/tutorials/prowler-app.mdx index 84095c7da2..ddbd489cdc 100644 --- a/docs/user-guide/tutorials/prowler-app.mdx +++ b/docs/user-guide/tutorials/prowler-app.mdx @@ -166,6 +166,6 @@ Once your scan has finished, you don’t need to grab the entire ZIP—just pull **API Note** -To fetch a single compliance report via API, see the Retrieve compliance report as CSV endpoint in the Prowler API Reference.[Prowler API Reference - Retrieve compliance report as CSV](https://api.prowler.com/api/v1/docs#tag/Scan/operation/scans_compliance_retrieve) +To fetch a single compliance report via API, see the Retrieve compliance report as CSV endpoint in the Prowler API Reference. [Prowler API Reference - Retrieve compliance report as CSV](https://api.prowler.com/api/v1/docs#tag/Scan/operation/scans_compliance_retrieve) From 03268445274b3d9052db1badab184e70efb8391f Mon Sep 17 00:00:00 2001 From: ye11oc4t <138095093+ye11oc4t@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:15:29 +0900 Subject: [PATCH 03/77] fix(github): paginate repository discovery (#12460) Co-authored-by: Daniel Barranquero --- .../github-repository-pagination.fixed.md | 1 + .../services/repository/repository_service.py | 104 ++++++++-- .../repository/repository_service_test.py | 191 ++++++++++++++++++ 3 files changed, 277 insertions(+), 19 deletions(-) create mode 100644 prowler/changelog.d/github-repository-pagination.fixed.md diff --git a/prowler/changelog.d/github-repository-pagination.fixed.md b/prowler/changelog.d/github-repository-pagination.fixed.md new file mode 100644 index 0000000000..e9add3d1a1 --- /dev/null +++ b/prowler/changelog.d/github-repository-pagination.fixed.md @@ -0,0 +1 @@ +GitHub repository discovery for unscoped scans now paginates beyond the first 100 accessible repositories instead of silently scanning only the first page diff --git a/prowler/providers/github/services/repository/repository_service.py b/prowler/providers/github/services/repository/repository_service.py index dc41df2ea5..f81d9781bb 100644 --- a/prowler/providers/github/services/repository/repository_service.py +++ b/prowler/providers/github/services/repository/repository_service.py @@ -10,6 +10,8 @@ from prowler.lib.logger import logger from prowler.providers.github.lib.service.service import GithubService from prowler.providers.github.models import GithubAppIdentityInfo +GITHUB_GRAPHQL_TIMEOUT = (10, 60) + class Repository(GithubService): def __init__(self, provider): @@ -65,41 +67,105 @@ class Repository(GithubService): "Content-Type": "application/json", } query = """ - { + query ($cursor: String) { viewer { - repositories(first: 100, affiliations: [OWNER, ORGANIZATION_MEMBER]) { + repositories( + first: 100 + after: $cursor + affiliations: [OWNER, ORGANIZATION_MEMBER] + ) { nodes { nameWithOwner } + pageInfo { + hasNextPage + endCursor + } } } } """ + repositories = [] + cursor = None + seen_cursors = set() + try: - response = requests.post( - graphql_url, json={"query": query}, headers=headers - ) - response.raise_for_status() - data = response.json() + while True: + response = requests.post( + graphql_url, + json={"query": query, "variables": {"cursor": cursor}}, + headers=headers, + timeout=GITHUB_GRAPHQL_TIMEOUT, + ) + response.raise_for_status() + data = response.json() - if "errors" in data: - logger.error(f"Error in GraphQL query: {data['errors']}") - return [] + errors = data.get("errors") if isinstance(data, dict) else None + repository_connection = ( + ((data.get("data") or {}).get("viewer") or {}).get("repositories") + if isinstance(data, dict) + else None + ) + if not isinstance(repository_connection, dict): + logger.error( + f"Error in GraphQL query: {errors or 'invalid response'}" + ) + return repositories + if errors: + # GitHub returns partial responses: repositories the token + # cannot access (e.g. behind organization SAML enforcement) + # come back as null nodes together with an "errors" entry, + # while the rest of the page is valid. + logger.warning( + f"GitHub GraphQL returned errors while discovering repositories, " + f"some repositories may be skipped: {errors}" + ) - repo_nodes = ( - data.get("data", {}) - .get("viewer", {}) - .get("repositories", {}) - .get("nodes", []) - ) - return [repo["nameWithOwner"] for repo in repo_nodes] + repo_nodes = repository_connection.get("nodes") + page_info = repository_connection.get("pageInfo") + if ( + not isinstance(repo_nodes, list) + or not isinstance(page_info, dict) + or not isinstance(page_info.get("hasNextPage"), bool) + ): + logger.error( + "GitHub GraphQL returned an invalid repositories page; " + "repository discovery may be incomplete." + ) + return repositories - except requests.exceptions.RequestException as error: + for repo_node in repo_nodes: + if not repo_node: + logger.warning( + "Skipping a repository the token cannot access during discovery." + ) + continue + repositories.append(repo_node["nameWithOwner"]) + + if not page_info["hasNextPage"]: + return repositories + + cursor = page_info.get("endCursor") + if not cursor or cursor in seen_cursors: + logger.error( + "GitHub GraphQL pagination returned an invalid cursor; " + "repository discovery may be incomplete." + ) + return repositories + seen_cursors.add(cursor) + + except ( + requests.exceptions.RequestException, + ValueError, + KeyError, + TypeError, + AttributeError, + ) as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - return [] + return repositories def _default_branch_matches_rule_pattern( self, pattern: str, default_branch: str diff --git a/tests/providers/github/services/repository/repository_service_test.py b/tests/providers/github/services/repository/repository_service_test.py index 4b77567e32..af174a6e54 100644 --- a/tests/providers/github/services/repository/repository_service_test.py +++ b/tests/providers/github/services/repository/repository_service_test.py @@ -1165,3 +1165,194 @@ class Test_Repository_List_Rate_Limit_Propagation: ): with raises(RateLimitExceededException): repository_service._list_repositories() + + +class Test_Repository_GraphQL_Pagination: + """Accessible repository discovery must follow GraphQL pagination.""" + + def _repository_service(self): + provider = set_mocked_github_provider() + provider.repositories = [] + provider.organizations = [] + with patch.object(Repository, "__init__", lambda *_: None): + repository_service = Repository(provider) + repository_service.clients = [MagicMock()] + repository_service.provider = provider + return repository_service + + @staticmethod + def _graphql_response(nodes, has_next_page=False, end_cursor=None, errors=None): + response = MagicMock() + payload = { + "data": { + "viewer": { + "repositories": { + "nodes": nodes, + "pageInfo": { + "hasNextPage": has_next_page, + "endCursor": end_cursor, + }, + } + } + } + } + if errors is not None: + payload["errors"] = errors + response.json.return_value = payload + return response + + def test_graphql_paginates_accessible_repositories(self): + repository_service = self._repository_service() + first_page_names = [f"owner/repo-{index}" for index in range(100)] + second_page_names = ["owner/repo-100"] + pages = [ + self._graphql_response( + [{"nameWithOwner": name} for name in first_page_names], + has_next_page=True, + end_cursor="page-2", + ), + self._graphql_response( + [{"nameWithOwner": name} for name in second_page_names] + ), + ] + + with patch("requests.post", side_effect=pages) as mock_post: + repositories = repository_service._get_accessible_repos_graphql() + + assert repositories == first_page_names + second_page_names + assert mock_post.call_count == 2 + first_request, second_request = mock_post.call_args_list + assert "after: $cursor" in first_request.kwargs["json"]["query"] + assert first_request.kwargs["json"]["variables"] == {"cursor": None} + assert second_request.kwargs["json"]["variables"] == {"cursor": "page-2"} + assert first_request.kwargs["timeout"] == (10, 60) + + def test_graphql_keeps_accessible_repositories_on_partial_errors(self): + """Per-node errors (e.g. SAML-protected repositories) must not drop the page.""" + repository_service = self._repository_service() + response = self._graphql_response( + [{"nameWithOwner": "owner/visible"}, None], + errors=[ + { + "type": "FORBIDDEN", + "path": ["viewer", "repositories", "nodes", 1], + "message": "Resource protected by organization SAML enforcement.", + } + ], + ) + + with ( + patch("requests.post", return_value=response), + patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger, + ): + repositories = repository_service._get_accessible_repos_graphql() + + assert repositories == ["owner/visible"] + assert mock_logger.warning.call_count == 2 + assert "SAML" in str(mock_logger.warning.call_args_list[0]) + + def test_graphql_later_page_failure_keeps_collected_repositories(self): + repository_service = self._repository_service() + first_page = self._graphql_response( + [{"nameWithOwner": "owner/first"}], has_next_page=True, end_cursor="page-2" + ) + + with ( + patch( + "requests.post", + side_effect=[ + first_page, + requests.exceptions.Timeout("second page timed out"), + ], + ) as mock_post, + patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger, + ): + repositories = repository_service._get_accessible_repos_graphql() + + assert repositories == ["owner/first"] + assert mock_post.call_count == 2 + mock_logger.error.assert_called_once() + assert "Timeout" in str(mock_logger.error.call_args) + + def test_graphql_errors_without_data_return_empty_list(self): + repository_service = self._repository_service() + response = MagicMock() + response.json.return_value = { + "data": None, + "errors": [{"type": "RATE_LIMITED", "message": "API rate limit exceeded"}], + } + + with ( + patch("requests.post", return_value=response), + patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger, + ): + repositories = repository_service._get_accessible_repos_graphql() + + assert repositories == [] + assert "RATE_LIMITED" in str(mock_logger.error.call_args) + + def test_graphql_stops_on_repeated_cursor(self): + repository_service = self._repository_service() + pages = [ + self._graphql_response( + [{"nameWithOwner": "owner/a"}], has_next_page=True, end_cursor="same" + ), + self._graphql_response( + [{"nameWithOwner": "owner/b"}], has_next_page=True, end_cursor="same" + ), + ] + + with ( + patch("requests.post", side_effect=pages) as mock_post, + patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger, + ): + repositories = repository_service._get_accessible_repos_graphql() + + assert repositories == ["owner/a", "owner/b"] + assert mock_post.call_count == 2 + mock_logger.error.assert_called_once() + + @pytest.mark.parametrize( + "nodes, page_info", + [ + ("not-a-list", {"hasNextPage": False}), + ({}, {"hasNextPage": False}), + (None, {"hasNextPage": False}), + ([{"nameWithOwner": "owner/b"}], ["invalid"]), + ([{"nameWithOwner": "owner/b"}], "invalid"), + ([{"nameWithOwner": "owner/b"}], []), + ([{"nameWithOwner": "owner/b"}], None), + ([{"nameWithOwner": "owner/b"}], {}), + ([{"nameWithOwner": "owner/b"}], {"hasNextPage": "false"}), + ], + ) + def test_graphql_invalid_page_keeps_collected_repositories(self, nodes, page_info): + repository_service = self._repository_service() + first_page = self._graphql_response( + [{"nameWithOwner": "owner/a"}], has_next_page=True, end_cursor="page-2" + ) + invalid_page = MagicMock() + invalid_page.json.return_value = { + "data": { + "viewer": {"repositories": {"nodes": nodes, "pageInfo": page_info}} + } + } + + with ( + patch("requests.post", side_effect=[first_page, invalid_page]), + patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger, + ): + repositories = repository_service._get_accessible_repos_graphql() + + assert repositories == ["owner/a"] + mock_logger.error.assert_called_once() From 89988dada574973c97d303a9c83f0b93c63d7535 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Mon, 31 Aug 2026 10:49:10 +0200 Subject: [PATCH 04/77] fix(ui): refresh cached permissions after token rotation (#12640) --- ui/actions/auth/auth.test.ts | 92 ++++ ui/actions/auth/auth.ts | 42 +- ui/auth.config.test.ts | 444 ++++++++++++++++++ ui/auth.config.ts | 29 ++ .../refresh-cached-permissions.fixed.md | 1 + ui/lib/auth-errors.ts | 9 + 6 files changed, 600 insertions(+), 17 deletions(-) create mode 100644 ui/changelog.d/refresh-cached-permissions.fixed.md create mode 100644 ui/lib/auth-errors.ts diff --git a/ui/actions/auth/auth.test.ts b/ui/actions/auth/auth.test.ts index 9b8b44e05b..016747b065 100644 --- a/ui/actions/auth/auth.test.ts +++ b/ui/actions/auth/auth.test.ts @@ -154,4 +154,96 @@ describe("auth actions", () => { expect(result.permissions.manage_lighthouse_ai_configuration).toBe(false); expect(result.permissions.manage_users).toBe(true); }); + + it("should forward an abort signal when loading the current user", async () => { + // Given + mockUserMe({ manage_users: true }); + const abortController = new AbortController(); + + // When + await getUserByMe("access-token", abortController.signal); + + // Then + expect(fetchMock).toHaveBeenCalledWith( + "https://api.example.com/api/v1/users/me?include=roles", + expect.objectContaining({ signal: abortController.signal }), + ); + }); + + it.each([ + { + status: 401, + detail: "Rejected by API", + message: "Invalid or expired token", + }, + { + status: 403, + detail: "Database password: super-secret", + message: "Access denied", + }, + { status: 404, detail: "Rejected by API", message: "User not found" }, + ])( + "should preserve a $status status when loading the current user fails", + async ({ status, detail, message }) => { + // Given + fetchMock.mockResolvedValue( + new Response(JSON.stringify({ errors: [{ detail }] }), { status }), + ); + + // When + const result = getUserByMe("access-token"); + + // Then + await expect(result).rejects.toMatchObject({ message, status }); + }, + ); + + it("should preserve a 401 status when the error body is not JSON", async () => { + // Given + fetchMock.mockResolvedValue(new Response("Unauthorized", { status: 401 })); + + // When + const result = getUserByMe("access-token"); + + // Then + await expect(result).rejects.toMatchObject({ + message: "Invalid or expired token", + status: 401, + }); + }); + + it("should preserve a 403 status when the error body is not JSON", async () => { + // Given + fetchMock.mockResolvedValue(new Response("Forbidden", { status: 403 })); + + // When + const result = getUserByMe("access-token"); + + // Then + await expect(result).rejects.toMatchObject({ + message: "Access denied", + status: 403, + }); + }); + + it("should not expose upstream details for unexpected errors", async () => { + // Given + fetchMock.mockResolvedValue( + new Response( + JSON.stringify({ + errors: [{ detail: "Database password: super-secret" }], + }), + { status: 500 }, + ), + ); + + // When + const result = getUserByMe("access-token"); + + // Then + await expect(result).rejects.toMatchObject({ + message: "Unable to load user", + status: 500, + }); + }); }); diff --git a/ui/actions/auth/auth.ts b/ui/actions/auth/auth.ts index 646c3d1426..0df5fe81c9 100644 --- a/ui/actions/auth/auth.ts +++ b/ui/actions/auth/auth.ts @@ -4,6 +4,7 @@ import { AuthError } from "next-auth"; import { signIn, signOut } from "@/auth.config"; import { apiBaseUrl } from "@/lib"; +import { UserMeError } from "@/lib/auth-errors"; import { addAuthEvent } from "@/lib/sentry-breadcrumbs"; import type { UtmParams } from "@/lib/utm"; import type { SignInFormData, SignUpFormData } from "@/types"; @@ -140,7 +141,10 @@ export const getToken = async (formData: SignInFormData) => { } }; -export const getUserByMe = async (accessToken: string) => { +export const getUserByMe = async ( + accessToken: string, + signal?: AbortSignal, +) => { const url = new URL(`${apiBaseUrl}/users/me?include=roles`); try { @@ -150,25 +154,23 @@ export const getUserByMe = async (accessToken: string) => { Accept: "application/vnd.api+json", Authorization: `Bearer ${accessToken}`, }, + signal, }); - const parsedResponse = await response.json(); if (!response.ok) { - // Handle different HTTP error codes - switch (response.status) { - case 401: - throw new Error("Invalid or expired token"); - case 403: - throw new Error(parsedResponse.errors?.[0]?.detail); - case 404: - throw new Error("User not found"); - default: - throw new Error( - parsedResponse.errors?.[0]?.detail || "Unknown error", - ); - } + const errorMessage = + response.status === 401 + ? "Invalid or expired token" + : response.status === 403 + ? "Access denied" + : response.status === 404 + ? "User not found" + : "Unable to load user"; + throw new UserMeError(errorMessage, response.status); } + const parsedResponse = await response.json(); + const userRole = parsedResponse.included?.find( (item: any) => item.type === "roles", ); @@ -193,8 +195,14 @@ export const getUserByMe = async (accessToken: string) => { dateJoined: parsedResponse.data.attributes.date_joined, permissions, }; - } catch (error: any) { - throw new Error(error.message || "Network error or server unreachable"); + } catch (error: unknown) { + if (error instanceof UserMeError) throw error; + + throw new UserMeError( + error instanceof Error + ? error.message + : "Network error or server unreachable", + ); } }; diff --git a/ui/auth.config.test.ts b/ui/auth.config.test.ts index 7125ce9845..a95461cb59 100644 --- a/ui/auth.config.test.ts +++ b/ui/auth.config.test.ts @@ -1,6 +1,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { authConfig } from "./auth.config"; +import { UserMeError } from "./lib/auth-errors"; import type { RolePermissionAttributes } from "./types/users"; const { getUserByMeMock } = vi.hoisted(() => ({ @@ -45,6 +46,35 @@ const ELEVATED_PERMISSIONS: RolePermissionAttributes = { manage_scans: true, }; +const accessTokenFor = (tenantId: string, expiration: number) => + `header.${Buffer.from( + JSON.stringify({ sub: "user-1", tenant_id: tenantId, exp: expiration }), + ).toString("base64url")}.signature`; + +const successfulRefreshResponse = (accessToken: string, refreshToken: string) => + new Response( + JSON.stringify({ + data: { + attributes: { + access: accessToken, + refresh: refreshToken, + }, + }, + }), + { status: 200 }, + ); + +const mockSuccessfulRefresh = ( + accessToken: string, + refreshToken = "new-refresh-token", +) => { + const fetchMock = vi + .fn() + .mockResolvedValue(successfulRefreshResponse(accessToken, refreshToken)); + vi.stubGlobal("fetch", fetchMock); + return fetchMock; +}; + describe("authConfig JWT callback", () => { beforeEach(() => { vi.clearAllMocks(); @@ -194,4 +224,418 @@ describe("authConfig JWT callback", () => { }); expect(result.error).toBeUndefined(); }); + + it("should replace restricted permissions after access token refresh", async () => { + // Given + const currentAccessToken = accessTokenFor("stale-tenant", 1); + const newAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + mockSuccessfulRefresh(newAccessToken); + getUserByMeMock.mockResolvedValue({ + name: "Tenant User", + email: "tenant@example.com", + company: "Tenant Company", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + + // When + const result = await jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "current-refresh-token", + user: { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: RESTRICTED_PERMISSIONS, + }, + }, + user: {} as Parameters[0]["user"], + }); + + // Then + expect(getUserByMeMock).toHaveBeenCalledWith( + newAccessToken, + expect.any(AbortSignal), + ); + expect(result).toMatchObject({ + accessToken: newAccessToken, + refreshToken: "new-refresh-token", + tenant_id: "tenant-1", + user: { + permissions: ELEVATED_PERMISSIONS, + }, + }); + expect(result.error).toBeUndefined(); + }); + + it("should replace elevated permissions when access is revoked", async () => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + const newAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + mockSuccessfulRefresh(newAccessToken); + getUserByMeMock.mockResolvedValue({ + name: "Tenant User", + email: "tenant@example.com", + company: "Tenant Company", + dateJoined: "2026-01-01", + permissions: RESTRICTED_PERMISSIONS, + }); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + + // When + const result = await jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "current-refresh-token", + user: { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }, + }, + user: {} as Parameters[0]["user"], + }); + + // Then + expect(getUserByMeMock).toHaveBeenCalledWith( + newAccessToken, + expect.any(AbortSignal), + ); + expect(result.user?.permissions).toEqual(RESTRICTED_PERMISSIONS); + expect(result.error).toBeUndefined(); + }); + + it("should keep the refreshed tokens and cached user when reloading the user fails", async () => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + const newAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + const warnSpy = vi + .spyOn(console, "warn") + .mockImplementation(() => undefined); + mockSuccessfulRefresh(newAccessToken); + getUserByMeMock.mockRejectedValue( + new UserMeError("Sensitive backend detail", 500), + ); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + const sessionCallback = authConfig.callbacks?.session; + if (!sessionCallback) throw new Error("Session callback is not configured"); + const cachedUser = { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }; + + // When + const result = await jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "current-refresh-token", + user: cachedUser, + }, + user: {} as Parameters[0]["user"], + }); + const session = await sessionCallback({ + session: { + expires: "2026-12-31T23:59:59.999Z", + user: { name: "Tenant User" }, + }, + token: result, + } as Parameters[0]); + + // Then + expect(session).toMatchObject({ + accessToken: newAccessToken, + refreshToken: "new-refresh-token", + tenantId: "tenant-1", + user: cachedUser, + }); + expect(result.error).toBeUndefined(); + expect(warnSpy).toHaveBeenCalledWith( + "Unable to refresh user after access token refresh", + ); + }); + + it("should bound a pending user reload and keep the refreshed session", async () => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + const newAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + const abortController = new AbortController(); + const timeoutSpy = vi + .spyOn(AbortSignal, "timeout") + .mockReturnValue(abortController.signal); + vi.spyOn(console, "warn").mockImplementation(() => undefined); + mockSuccessfulRefresh(newAccessToken); + getUserByMeMock.mockImplementation( + (_accessToken: string, signal?: AbortSignal) => { + if (!signal) return Promise.reject(new Error("Missing abort signal")); + + return new Promise((_resolve, reject) => { + signal.addEventListener("abort", () => reject(signal.reason), { + once: true, + }); + }); + }, + ); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + const cachedUser = { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }; + + // When + const resultPromise = jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "current-refresh-token", + user: cachedUser, + }, + user: {} as Parameters[0]["user"], + }); + await vi.waitFor(() => expect(getUserByMeMock).toHaveBeenCalled()); + + // Then + expect(timeoutSpy).toHaveBeenCalledWith(5_000); + expect(getUserByMeMock).toHaveBeenCalledWith( + newAccessToken, + abortController.signal, + ); + + abortController.abort( + new DOMException("Request timed out", "TimeoutError"), + ); + await expect(resultPromise).resolves.toMatchObject({ + accessToken: newAccessToken, + refreshToken: "new-refresh-token", + user: cachedUser, + error: undefined, + }); + }); + + it.each([401, 403, 404])( + "should invalidate the session when reloading the user returns %i", + async (status) => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + const newAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + vi.spyOn(console, "warn").mockImplementation(() => undefined); + mockSuccessfulRefresh(newAccessToken); + getUserByMeMock.mockRejectedValue( + new UserMeError("Unable to load user", status), + ); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + const sessionCallback = authConfig.callbacks?.session; + if (!sessionCallback) + throw new Error("Session callback is not configured"); + + // When + const result = await jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "current-refresh-token", + user: { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }, + }, + user: {} as Parameters[0]["user"], + }); + const session = await sessionCallback({ + session: { + expires: "2026-12-31T23:59:59.999Z", + user: { name: "Tenant User" }, + }, + token: result, + } as Parameters[0]); + + // Then + expect(result.user).toBeUndefined(); + expect(result.accessToken).toBeUndefined(); + expect(result.refreshToken).toBeUndefined(); + expect(result.error).toBe("RefreshAccessTokenError"); + expect(session.user).toBeUndefined(); + expect(session.accessToken).toBeUndefined(); + expect(session.refreshToken).toBeUndefined(); + }, + ); + + it("should invalidate the session when access token refresh fails", async () => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + vi.spyOn(console, "warn").mockImplementation(() => undefined); + vi.stubGlobal( + "fetch", + vi + .fn() + .mockResolvedValue( + new Response( + JSON.stringify({ errors: [{ detail: "Refresh token expired" }] }), + { status: 401 }, + ), + ), + ); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + const sessionCallback = authConfig.callbacks?.session; + if (!sessionCallback) throw new Error("Session callback is not configured"); + + // When + const result = await jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "expired-refresh-token", + user: { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }, + }, + user: {} as Parameters[0]["user"], + }); + const session = await sessionCallback({ + session: { + expires: "2026-12-31T23:59:59.999Z", + user: { name: "Tenant User" }, + }, + token: result, + } as Parameters[0]); + + // Then + expect(getUserByMeMock).not.toHaveBeenCalled(); + expect(result.error).toBe("RefreshAccessTokenError"); + expect(session.error).toBe("RefreshAccessTokenError"); + expect(session.user).toBeUndefined(); + expect(session.accessToken).toBeUndefined(); + expect(session.refreshToken).toBeUndefined(); + expect(session.tenantId).toBeUndefined(); + }); + + it("should deduplicate concurrent token and user refreshes", async () => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + const newAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + const fetchMock = mockSuccessfulRefresh(newAccessToken); + getUserByMeMock.mockResolvedValue({ + name: "Tenant User", + email: "tenant@example.com", + company: "Tenant Company", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + const currentToken = { + accessToken: currentAccessToken, + refreshToken: "shared-refresh-token", + user: { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: RESTRICTED_PERMISSIONS, + }, + }; + + // When + const [firstResult, secondResult] = await Promise.all([ + jwtCallback({ + token: { ...currentToken }, + user: {} as Parameters[0]["user"], + }), + jwtCallback({ + token: { ...currentToken }, + user: {} as Parameters[0]["user"], + }), + ]); + + // Then + expect(fetchMock).toHaveBeenCalledTimes(1); + expect(getUserByMeMock).toHaveBeenCalledTimes(1); + expect(firstResult).toEqual(secondResult); + expect(firstResult.user?.permissions).toEqual(ELEVATED_PERMISSIONS); + }); + + it("should retry reloading the user on the next token rotation", async () => { + // Given + const currentAccessToken = accessTokenFor("tenant-1", 1); + const firstAccessToken = accessTokenFor("tenant-1", 1); + const secondAccessToken = accessTokenFor("tenant-1", 4_102_444_800); + vi.spyOn(console, "warn").mockImplementation(() => undefined); + const fetchMock = vi + .fn() + .mockResolvedValueOnce( + successfulRefreshResponse( + firstAccessToken, + "first-rotated-refresh-token", + ), + ) + .mockResolvedValueOnce( + successfulRefreshResponse( + secondAccessToken, + "second-rotated-refresh-token", + ), + ); + vi.stubGlobal("fetch", fetchMock); + getUserByMeMock + .mockRejectedValueOnce(new Error("Temporary API failure")) + .mockResolvedValueOnce({ + name: "Tenant User", + email: "tenant@example.com", + company: "Tenant Company", + dateJoined: "2026-01-01", + permissions: RESTRICTED_PERMISSIONS, + }); + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + + // When + const firstResult = await jwtCallback({ + token: { + accessToken: currentAccessToken, + refreshToken: "current-refresh-token", + user: { + name: "Tenant User", + email: "tenant@example.com", + dateJoined: "2026-01-01", + permissions: ELEVATED_PERMISSIONS, + }, + }, + user: {} as Parameters[0]["user"], + }); + const secondResult = await jwtCallback({ + token: firstResult, + user: {} as Parameters[0]["user"], + }); + + // Then + expect(fetchMock).toHaveBeenCalledTimes(2); + expect(getUserByMeMock).toHaveBeenNthCalledWith( + 1, + firstAccessToken, + expect.any(AbortSignal), + ); + expect(getUserByMeMock).toHaveBeenNthCalledWith( + 2, + secondAccessToken, + expect.any(AbortSignal), + ); + expect(firstResult.user?.permissions).toEqual(ELEVATED_PERMISSIONS); + expect(secondResult).toMatchObject({ + accessToken: secondAccessToken, + refreshToken: "second-rotated-refresh-token", + user: { permissions: RESTRICTED_PERMISSIONS }, + }); + }); }); diff --git a/ui/auth.config.ts b/ui/auth.config.ts index f84ff6496d..ec6880e193 100644 --- a/ui/auth.config.ts +++ b/ui/auth.config.ts @@ -11,6 +11,7 @@ import { z } from "zod"; import { getToken, getUserByMe } from "./actions/auth"; import { apiBaseUrl } from "./lib"; +import { UserMeError } from "./lib/auth-errors"; import { SLACK_CALLBACK_PATH, SLACK_EXPIRED_CALLBACK_URL, @@ -64,6 +65,9 @@ const DEFAULT_PERMISSIONS: RolePermissionAttributes = { const TENANT_SWITCH_ERROR = "TenantSwitchError"; +const NON_RETRYABLE_USER_ME_STATUSES = new Set([401, 403, 404]); +const USER_REFRESH_TIMEOUT_MS = 5_000; + type TokenUserInput = Partial & { company?: string }; type JwtCallback = NonNullable["jwt"]>; @@ -206,6 +210,31 @@ const refreshAccessToken = async (token: AuthToken): Promise => { applyDecodedClaims(nextToken, newAccessToken, "refreshed access token"); + try { + const userMeResponse = await getUserByMe( + newAccessToken, + AbortSignal.timeout(USER_REFRESH_TIMEOUT_MS), + ); + nextToken.user = tokenUserFromApi(userMeResponse); + } catch (error) { + if ( + error instanceof UserMeError && + error.status !== undefined && + NON_RETRYABLE_USER_ME_STATUSES.has(error.status) + ) { + return { + ...nextToken, + accessToken: undefined, + refreshToken: undefined, + user: undefined, + error: "RefreshAccessTokenError", + }; + } + + // eslint-disable-next-line no-console + console.warn("Unable to refresh user after access token refresh"); + } + return nextToken; } catch (error) { // eslint-disable-next-line no-console diff --git a/ui/changelog.d/refresh-cached-permissions.fixed.md b/ui/changelog.d/refresh-cached-permissions.fixed.md new file mode 100644 index 0000000000..2a93ce6f29 --- /dev/null +++ b/ui/changelog.d/refresh-cached-permissions.fixed.md @@ -0,0 +1 @@ +Cached permissions now refresh from `/users/me?include=roles` after access token rotation diff --git a/ui/lib/auth-errors.ts b/ui/lib/auth-errors.ts new file mode 100644 index 0000000000..343252e0e3 --- /dev/null +++ b/ui/lib/auth-errors.ts @@ -0,0 +1,9 @@ +export class UserMeError extends Error { + constructor( + message: string, + public readonly status?: number, + ) { + super(message); + this.name = "UserMeError"; + } +} From f05a490cd74a2c0f11a5d66d8ce29d03fa5c64a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Mon, 31 Aug 2026 10:57:58 +0200 Subject: [PATCH 05/77] feat(mcp): raise instead of returning error objects in the Prowler App tools (#12532) --- .../mcp-app-tool-failures.added.md | 1 + ...mcp-compliance-scan-or-provider.changed.md | 1 + mcp_server/prowler_mcp_server/lib/errors.py | 29 +- mcp_server/prowler_mcp_server/lib/types.py | 18 + .../prowler_app/models/attack_paths.py | 18 +- .../prowler_app/models/providers.py | 25 +- .../prowler_app/models/scans.py | 39 +- .../prowler_mcp_server/prowler_app/server.py | 2 +- .../prowler_app/tools/attack_paths.py | 202 +++++---- .../prowler_app/tools/compliance.py | 55 +-- .../prowler_app/tools/finding_groups.py | 198 +++++---- .../prowler_app/tools/findings.py | 3 +- .../prowler_app/tools/integrations.py | 382 +++++++++--------- .../prowler_app/tools/muting.py | 117 +++--- .../prowler_app/tools/providers.py | 234 ++++++++--- .../prowler_app/tools/resources.py | 5 +- .../prowler_app/tools/roles.py | 30 +- .../prowler_app/tools/scans.py | 141 ++++--- .../prowler_app/tools/users.py | 3 +- .../prowler_app/utils/api_client.py | 16 +- .../prowler_app/utils/auth.py | 46 ++- .../prowler_documentation/server.py | 7 +- .../prowler_mcp_server/prowler_hub/server.py | 19 +- mcp_server/tests/lib/test_errors.py | 34 +- mcp_server/tests/lib/test_types.py | 125 ++++++ .../prowler_app/tools/test_attack_paths.py | 225 +++++++++++ .../prowler_app/tools/test_compliance.py | 102 +++++ .../prowler_app/tools/test_integrations.py | 156 +++---- .../tests/prowler_app/tools/test_muting.py | 64 +++ .../tests/prowler_app/tools/test_providers.py | 316 +++++++++++++++ .../tests/prowler_app/tools/test_roles.py | 147 +++++++ .../tests/prowler_app/tools/test_scans.py | 201 +++++++++ .../tests/prowler_app/utils/test_auth.py | 85 +++- 33 files changed, 2364 insertions(+), 682 deletions(-) create mode 100644 mcp_server/changelog.d/mcp-app-tool-failures.added.md create mode 100644 mcp_server/changelog.d/mcp-compliance-scan-or-provider.changed.md create mode 100644 mcp_server/prowler_mcp_server/lib/types.py create mode 100644 mcp_server/tests/lib/test_types.py create mode 100644 mcp_server/tests/prowler_app/tools/test_attack_paths.py create mode 100644 mcp_server/tests/prowler_app/tools/test_compliance.py create mode 100644 mcp_server/tests/prowler_app/tools/test_muting.py create mode 100644 mcp_server/tests/prowler_app/tools/test_providers.py create mode 100644 mcp_server/tests/prowler_app/tools/test_roles.py create mode 100644 mcp_server/tests/prowler_app/tools/test_scans.py diff --git a/mcp_server/changelog.d/mcp-app-tool-failures.added.md b/mcp_server/changelog.d/mcp-app-tool-failures.added.md new file mode 100644 index 0000000000..c51daa6c86 --- /dev/null +++ b/mcp_server/changelog.d/mcp-app-tool-failures.added.md @@ -0,0 +1 @@ +Prowler App tools now report a failure as an MCP tool execution error (`isError: true`, explanation in `content`) instead of as a successful result carrying an `{"error": ...}` object, which clients and models read as a success diff --git a/mcp_server/changelog.d/mcp-compliance-scan-or-provider.changed.md b/mcp_server/changelog.d/mcp-compliance-scan-or-provider.changed.md new file mode 100644 index 0000000000..04eebef825 --- /dev/null +++ b/mcp_server/changelog.d/mcp-compliance-scan-or-provider.changed.md @@ -0,0 +1 @@ +`prowler_get_compliance_framework_state_details` now rejects a call that passes both `scan_id` and `provider_id` instead of silently ignoring the provider, which could report on a scan belonging to a different provider than the one that was asked about diff --git a/mcp_server/prowler_mcp_server/lib/errors.py b/mcp_server/prowler_mcp_server/lib/errors.py index 29e2db6481..9491bf87eb 100644 --- a/mcp_server/prowler_mcp_server/lib/errors.py +++ b/mcp_server/prowler_mcp_server/lib/errors.py @@ -19,10 +19,17 @@ class ProwlerAPIError(Exception): Attributes: status_code: HTTP status the API answered with detail: JSON:API `errors[0].detail`, None when there is none to trust + payload: Parsed JSON body, for a tool that has to read the answer rather + than only report it """ def __init__( - self, message: str, status_code: int, *, detail: str | None = None + self, + message: str, + status_code: int, + *, + detail: str | None = None, + payload: dict[str, Any] | None = None, ) -> None: super().__init__(message) self.status_code: int = status_code @@ -32,6 +39,12 @@ class ProwlerAPIError(Exception): # that must never be repeated to a model -- and None for a 5xx, see # `jsonapi_detail`. self.detail: str | None = detail + # Not every error status means the request failed: Prowler answers 404 + # with the result itself when a query ran and matched nothing. A tool + # reads this to tell such an answer apart from a real failure. It is the + # upstream body, so it is read structurally and never relayed as text -- + # `detail` above is the only part of it that may be repeated to a model. + self.payload: dict[str, Any] | None = payload class ProwlerAPIUnreachable(Exception): @@ -71,6 +84,10 @@ class InvalidArgument(ValueError): """An argument this server rejected before any request went out.""" +class CredentialError(Exception): + """The credential the caller sent is missing, malformed or expired.""" + + # ------------------------------------------------------------------- messages @@ -154,6 +171,16 @@ def _describe_failure(exc: BaseException) -> str | None: "current state before sending it again." ) + if isinstance(exc, CredentialError): + # Not an argument problem, so it is worth saying that plainly: the + # answer is a credential the user has to fix, not another attempt. + return ( + f"This request carried no usable credential: {exc}. Retrying or " + "changing the arguments will not help -- the client has to send an " + "'Authorization: Bearer ' header holding a valid Prowler API " + "key or an unexpired JWT." + ) + if isinstance(exc, ProwlerAPIUnreachable): # The only failure a model can turn into a duplicate write by repeating. return ( diff --git a/mcp_server/prowler_mcp_server/lib/types.py b/mcp_server/prowler_mcp_server/lib/types.py new file mode 100644 index 0000000000..5381b21e8a --- /dev/null +++ b/mcp_server/prowler_mcp_server/lib/types.py @@ -0,0 +1,18 @@ +"""Argument types shared by every tool in this server.""" + +from typing import Annotated + +from pydantic import StringConstraints + +# The identifiers tools take -- a scan UUID, a query id, a Jira project key -- +# are required because there is nothing sensible to do without them. A model +# that does not have one to hand tends to send an empty string rather than omit +# the argument, and an empty string is not caught by "required": it travels into +# a URL path or a request body and comes back as a 404 or an opaque API error +# ("This field may not be blank") that says nothing about which argument was at +# fault. Rejecting it here names the argument instead, and `minLength` puts the +# constraint in the tool schema so a client can see it before calling. +# +# Whitespace is stripped first, so " abc " is accepted as "abc" and " " is +# rejected like "". +NonBlankStr = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)] diff --git a/mcp_server/prowler_mcp_server/prowler_app/models/attack_paths.py b/mcp_server/prowler_mcp_server/prowler_app/models/attack_paths.py index bbe2eb7401..acaacac540 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/models/attack_paths.py +++ b/mcp_server/prowler_mcp_server/prowler_app/models/attack_paths.py @@ -354,6 +354,14 @@ class AttackPathQueryResult(MinimalSerializerMixin, BaseModel): relationships: list[AttackPathsGraphRelationship] = Field( default_factory=list, description="Relationships connecting the nodes" ) + # A graph with nothing in it serializes to `{}`, since the mixin drops empty + # lists. That reads as an answer that went missing rather than as the finding + # it is -- the query ran and this account has no such attack path -- so the + # empty case carries a sentence saying so. + message: str | None = Field( + default=None, + description="Present only when the query matched nothing, to say the query ran and found no attack path rather than leaving an empty result to interpret", + ) @classmethod def from_api_response( @@ -368,7 +376,15 @@ class AttackPathQueryResult(MinimalSerializerMixin, BaseModel): Returns: AttackPathQueryResult with parsed data and summary """ - attributes = response.get("data", {}).get("attributes") + data = response.get("data") + attributes = data.get("attributes") if data is not None else None + # Prowler spells a graph with nothing in it either as empty lists or as + # a null `attributes`. Both say the same thing -- the query ran and + # matched nothing -- so the null reads as the empty graph it stands for + # instead of crashing the parse. + if attributes is None: + attributes = {} + nodes_data = attributes.get("nodes", []) relationships_data = attributes.get("relationships", []) diff --git a/mcp_server/prowler_mcp_server/prowler_app/models/providers.py b/mcp_server/prowler_mcp_server/prowler_app/models/providers.py index af9509a963..322d85186c 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/models/providers.py +++ b/mcp_server/prowler_mcp_server/prowler_app/models/providers.py @@ -2,7 +2,7 @@ from typing import Any, Literal -from pydantic import BaseModel +from pydantic import BaseModel, ConfigDict, Field from prowler_mcp_server.prowler_app.models.base import MinimalSerializerMixin @@ -104,6 +104,29 @@ class ProvidersListResponse(BaseModel): ) +class ProviderDeletionResult(MinimalSerializerMixin, BaseModel): + """Outcome of a provider deletion. + + Prowler deletes a provider in a background task, so the answer is not always + a finished deletion. A deletion that never started is raised as an error + instead of being reported here: this model only describes a deletion Prowler + accepted and began. + """ + + model_config = ConfigDict(frozen=True) + + status: Literal["deleted", "in_progress"] = Field( + description="Outcome of the deletion: 'deleted' when Prowler finished removing the provider, 'in_progress' when the background task was accepted and is still running, which is normal for a provider with many scans and findings" + ) + task_id: str | None = Field( + default=None, + description="UUIDv4 of the background deletion task, present when the deletion did not finish within the polling window so its state can be checked later", + ) + message: str = Field( + description="Human-readable description of what happened and what to do next" + ) + + class ProviderConnectionStatus(MinimalSerializerMixin, BaseModel): """Result of provider connection operation.""" diff --git a/mcp_server/prowler_mcp_server/prowler_app/models/scans.py b/mcp_server/prowler_mcp_server/prowler_app/models/scans.py index f8eef988ce..3fc095eaa8 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/models/scans.py +++ b/mcp_server/prowler_mcp_server/prowler_app/models/scans.py @@ -191,18 +191,18 @@ class ScansListResponse(BaseModel): class ScanCreationResult(MinimalSerializerMixin, BaseModel): - """Result of scan creation operation. + """Result of a scan creation that succeeded. - Used by trigger_scan() to communicate the outcome of scan creation. - Status indicates whether scan was created successfully or failed. + Used by trigger_scan(). A scan that was not created leaves the tool as an + error instead of being reported here, so this model only ever describes a + scan that exists -- which is why it carries no success flag: a field with + one reachable value says nothing, and inviting a reader to branch on it + suggests there is a failure shape to look for here. There is not; the + failure is the error. """ - scan: DetailedScan | None = Field( - default=None, - description="Detailed scan information if creation succeeded, None otherwise", - ) - status: Literal["success", "failed"] = Field( - description="Outcome of scan creation: success (scan created successfully) or failed (error)" + scan: DetailedScan = Field( + description="Detailed information about the scan that was created" ) message: str = Field( description="Human-readable message describing the scan creation result" @@ -210,13 +210,26 @@ class ScanCreationResult(MinimalSerializerMixin, BaseModel): class ScheduleCreationResult(MinimalSerializerMixin, BaseModel): - """Result of async schedule creation operation. + """Result of a daily schedule creation that succeeded. - Used by schedule_daily_scan() to communicate scheduling outcome. + Used by schedule_daily_scan(). Prowler commits the schedule inside the + request that creates it, so an answer means it exists; a provider that + already has one is refused with a 409 and leaves the tool as an error. That + leaves nothing for a success flag to distinguish, so there is none. """ - scheduled: bool = Field( - description="Whether the daily scan schedule was created successfully" + first_run_state: ( + Literal[ + "available", "scheduled", "executing", "completed", "failed", "cancelled" + ] + | None + ) = Field( + default=None, + description=( + "State of the first scan Prowler starts immediately alongside the schedule. " + "This describes that one run, not the recurring schedule, which stands " + "regardless of it" + ), ) message: str = Field( description="Human-readable message describing the scheduling result" diff --git a/mcp_server/prowler_mcp_server/prowler_app/server.py b/mcp_server/prowler_mcp_server/prowler_app/server.py index e8e854144f..3129a50d09 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/server.py +++ b/mcp_server/prowler_mcp_server/prowler_app/server.py @@ -3,7 +3,7 @@ from fastmcp import FastMCP from prowler_mcp_server.prowler_app.utils.tool_loader import load_all_tools # Initialize MCP server -app_mcp_server = FastMCP("prowler-app") +app_mcp_server = FastMCP("prowler-app", mask_error_details=True) # Auto-discover and load all tools from the tools package load_all_tools(app_mcp_server) diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/attack_paths.py b/mcp_server/prowler_mcp_server/prowler_app/tools/attack_paths.py index 5bd66760fa..b1914dc795 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/attack_paths.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/attack_paths.py @@ -7,8 +7,11 @@ through cloud infrastructure relationships. from typing import Any, Literal +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.errors import ProwlerAPIError +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.attack_paths import ( AttackPathCartographySchema, AttackPathQuery, @@ -76,50 +79,47 @@ class AttackPathsTools(BaseTool): 2. Use prowler_list_attack_paths_queries to see available queries for a scan 3. Use prowler_run_attack_paths_query to execute analysis """ - try: - # Validate pagination - self.api_client.validate_page_size(page_size) + # Validate pagination + self.api_client.validate_page_size(page_size) - # Build query parameters - params: dict[str, Any] = { - "page[size]": page_size, - "page[number]": page_number, - } + # Build query parameters + params: dict[str, Any] = { + "page[size]": page_size, + "page[number]": page_number, + } - # Apply provider filters - if provider_id: - params["filter[provider__in]"] = provider_id - if provider_type: - params["filter[provider_type__in]"] = provider_type + # Apply provider filters + if provider_id: + params["filter[provider__in]"] = provider_id + if provider_type: + params["filter[provider_type__in]"] = provider_type - # Apply state filter - if state: - params["filter[state__in]"] = state + # Apply state filter + if state: + params["filter[state__in]"] = state - clean_params = self.api_client.build_filter_params(params) + clean_params = self.api_client.build_filter_params(params) - api_response = await self.api_client.get( - "/attack-paths-scans", params=clean_params - ) - simplified_response = AttackPathScansListResponse.from_api_response( - api_response - ) + api_response = await self.api_client.get( + "/attack-paths-scans", params=clean_params + ) + simplified_response = AttackPathScansListResponse.from_api_response( + api_response + ) - return simplified_response.model_dump() - except Exception as e: - self.logger.error(f"Failed to list attack paths scans: {e}") - return {"error": f"Failed to list attack paths scans: {str(e)}"} + return simplified_response.model_dump() async def list_attack_paths_queries( self, - scan_id: str = Field( - description="UUID of a COMPLETED attack paths scan. Use `prowler_list_attack_paths_scans` with state=['completed'] to find scan IDs" + scan_id: NonBlankStr = Field( + description="UUID of a COMPLETED attack paths scan, as returned by `prowler_list_attack_paths_scans` with state=['completed']. This is NOT a regular scan ID: an ID from `prowler_search_scans` or `prowler_get_scan` names a different resource and is rejected here" ), ) -> list[dict[str, Any]]: """Discover available Attack Paths queries for a completed scan. IMPORTANT: The scan must be in 'completed' state to list queries. - Queries are provider-specific + Attack Paths covers AWS providers only, so only an AWS provider has an + Attack Paths scan to name here, and every query is an AWS one. Each query includes: - id: Query identifier to use with run_attack_paths_query @@ -141,23 +141,32 @@ class AttackPathsTools(BaseTool): api_response = await self.api_client.get( f"/attack-paths-scans/{scan_id}/queries" ) + except ProwlerAPIError as e: + # A 404 here is Prowler failing to resolve `scan_id` to an Attack + # Paths scan, and its own reason for it -- a bare "Not found." -- + # does not say what kind of ID it was looking for. The mistake it + # stands for is a regular scan ID: an Attack Paths scan is a separate + # resource with IDs of its own, and Prowler only creates one for an + # AWS provider, so a scan of any other provider has none to pass. + # + # The endpoint answers 404 for a second thing -- a provider type with + # no query catalog -- but that one cannot happen: a scan only exists + # where Attack Paths runs, which is AWS, and AWS has a catalog. + if e.status_code == 404: + raise self._unknown_scan_error(scan_id) + raise - return [ - AttackPathQuery.from_api_response(query).model_dump() - for query in api_response.get("data", []) - ] - except Exception as e: - self.logger.error( - f"Failed to list attack paths queries for scan {scan_id}: {e}" - ) - return [{"error": f"Failed to list attack paths queries: {str(e)}"}] + return [ + AttackPathQuery.from_api_response(query).model_dump() + for query in api_response.get("data", []) + ] async def run_attack_paths_query( self, - scan_id: str = Field( + scan_id: NonBlankStr = Field( description="UUID of a COMPLETED attack paths scan. The scan must be in 'completed' state" ), - query_id: str = Field( + query_id: NonBlankStr = Field( description="Query ID to execute (e.g., 'aws-internet-exposed-ec2-sensitive-s3-access'). Use `prowler_list_attack_paths_queries` to discover available queries" ), parameters: dict[str, str] = Field( @@ -198,39 +207,61 @@ class AttackPathsTools(BaseTool): 3. Execute this tool with appropriate parameters 4. Analyze the returned graph for security insights """ - try: - # Build the request payload following JSON:API format - request_data: dict[str, Any] = { - "data": { - "type": "attack-paths-query-run-requests", - "attributes": { - "id": query_id, - }, + # Build the request payload following JSON:API format + request_data: dict[str, Any] = { + "data": { + "type": "attack-paths-query-run-requests", + "attributes": { + "id": query_id, }, - } + }, + } - # Add parameters if provided - if parameters: - request_data["data"]["attributes"]["parameters"] = parameters + # Add parameters if provided + if parameters: + request_data["data"]["attributes"]["parameters"] = parameters + try: api_response = await self.api_client.post( f"/attack-paths-scans/{scan_id}/queries/run", json_data=request_data, ) + except ProwlerAPIError as e: + # Prowler answers a query that matched nothing with 404 and the empty + # result as the body. That is an answer -- this account has no such + # attack path, which is the good outcome -- so it is returned rather + # than raised: reporting it as a failure invites a retry of a call + # whose arguments were right, and hides a clean result. + if e.status_code == 404 and isinstance(e.payload, dict): + if "data" in e.payload: + api_response = e.payload + else: + # No result body, so `scan_id` did not resolve to an Attack + # Paths scan. An unknown query_id is a 400, not this. + raise self._unknown_scan_error(scan_id) + else: + raise - # Parse the response - query_result = AttackPathQueryResult.from_api_response(api_response) + # Parse the response + query_result = AttackPathQueryResult.from_api_response(api_response) - return query_result.model_dump() - except Exception as e: - self.logger.error( - f"Failed to run attack paths query '{query_id}' on scan {scan_id}: {e}" + if not query_result.nodes: + query_result = query_result.model_copy( + update={ + "message": ( + f"The query '{query_id}' ran against scan {scan_id} and matched " + "nothing, so this provider has no attack path of that shape. " + "The scan and the query ID were both valid; running it again " + "will return the same thing." + ) + } ) - return {"error": f"Failed to run attack paths query '{query_id}': {str(e)}"} + + return query_result.model_dump() async def get_attack_paths_cartography_schema( self, - scan_id: str = Field( + scan_id: NonBlankStr = Field( description="UUID of a COMPLETED attack paths scan. Use `prowler_list_attack_paths_scans` with state=['completed'] to find scan IDs" ), ) -> dict[str, Any]: @@ -262,18 +293,43 @@ class AttackPathsTools(BaseTool): api_response = await self.api_client.get( f"/attack-paths-scans/{scan_id}/schema" ) + except ProwlerAPIError as e: + # Two 404s again, told apart by whether Prowler wrote a JSON:API + # error. Absent means the scan resolved and its graph simply records + # no Cartography module, so the ID is not the thing to change. + if e.status_code == 404: + if e.detail is None: + raise ToolError( + f"Scan {scan_id} has no Cartography schema recorded, so there is " + "nothing to write custom queries against. Use " + "prowler_list_attack_paths_queries for the ready-made queries of " + "this scan, which do not need the schema." + ) + else: + raise self._unknown_scan_error(scan_id) + raise - schema = AttackPathCartographySchema.from_api_response(api_response) + schema = AttackPathCartographySchema.from_api_response(api_response) - schema_content = await self.api_client.fetch_external_url( - schema.raw_schema_url - ) + schema_content = await self.api_client.fetch_external_url(schema.raw_schema_url) - return schema.model_copy( - update={"schema_content": schema_content} - ).model_dump() - except Exception as e: - self.logger.error( - f"Failed to get cartography schema for scan {scan_id}: {e}" - ) - return {"error": f"Failed to get cartography schema: {str(e)}"} + return schema.model_copy(update={"schema_content": schema_content}).model_dump() + + # Private helper methods + + @staticmethod + def _unknown_scan_error(scan_id: str) -> ToolError: + """Describe a scan ID Prowler could not resolve to an Attack Paths scan. + + Returns: + The ``ToolError`` for the caller to raise. Built without a ``from`` + clause on purpose: the sentence is the final word, not a wrapper + around the API's. + """ + return ToolError( + f"Prowler has no Attack Paths scan with ID {scan_id}. These are a " + "different resource from regular scans and only exist for AWS " + "providers, so an ID from prowler_search_scans or prowler_get_scan " + "never resolves here. Use prowler_list_attack_paths_scans to get an " + "ID these tools take." + ) diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/compliance.py b/mcp_server/prowler_mcp_server/prowler_app/tools/compliance.py index 33cdd22a69..b7f06be9a8 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/compliance.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/compliance.py @@ -6,8 +6,11 @@ across all cloud providers. from typing import Any +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.errors import InvalidArgument +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.compliance import ( ComplianceFrameworksListResponse, ComplianceRequirementAttributesListResponse, @@ -34,7 +37,7 @@ class ComplianceTools(BaseTool): The scan_id of the latest completed scan for the provider. Raises: - ValueError: If no completed scans are found for the provider. + ToolError: If no completed scans are found for the provider """ scan_params = { "filter[provider]": provider_id, @@ -48,7 +51,7 @@ class ComplianceTools(BaseTool): scans_data = scans_response.get("data", []) if not scans_data: - raise ValueError( + raise ToolError( f"No completed scans found for provider {provider_id}. " "Run a scan first using prowler_trigger_scan." ) @@ -93,18 +96,15 @@ class ComplianceTools(BaseTool): 2. Use prowler_get_compliance_framework_state_details with a specific compliance_id to see which requirements failed """ if not scan_id and not provider_id: - return { - "error": "Either scan_id or provider_id must be provided. Use prowler_search_providers to find provider IDs or prowler_list_scans to find scan IDs." - } + raise InvalidArgument( + "Either scan_id or provider_id must be provided. Use prowler_search_providers to find provider IDs or prowler_list_scans to find scan IDs." + ) elif scan_id and provider_id: - return { - "error": "Provide either scan_id or provider_id, not both. To get compliance data for a specific scan, use scan_id. To get data for the latest scan of a provider, use provider_id." - } + raise InvalidArgument( + "Provide either scan_id or provider_id, not both. To get compliance data for a specific scan, use scan_id. To get data for the latest scan of a provider, use provider_id." + ) elif not scan_id and provider_id: - try: - scan_id = await self._get_latest_scan_id_for_provider(provider_id) - except ValueError as e: - return {"error": str(e)} + scan_id = await self._get_latest_scan_id_for_provider(provider_id) params: dict[str, Any] = {"filter[scan_id]": scan_id} @@ -253,16 +253,16 @@ class ComplianceTools(BaseTool): async def get_compliance_framework_state_details( self, - compliance_id: str = Field( + compliance_id: NonBlankStr = Field( description="Compliance framework ID to get details for (e.g., 'cis_1.5_aws', 'pci_dss_v4.0_aws'). You can get compliance IDs from prowler_get_compliance_overview or consulting Prowler Hub/Prowler Documentation that you can also find in form of tools in this MCP Server", ), scan_id: str | None = Field( default=None, - description="UUID of a specific scan to get compliance data for. Required if provider_id is not specified.", + description="UUID of a specific scan to get compliance data for. Required if provider_id is not specified. Do not pass it together with provider_id.", ), provider_id: str | None = Field( default=None, - description="Prowler's internal UUID (v4) for a specific provider. If provided without scan_id, the tool will automatically find the latest completed scan for this provider. Use `prowler_search_providers` tool to find provider IDs.", + description="Prowler's internal UUID (v4) for a specific provider. The tool will automatically find the latest completed scan for this provider. Use `prowler_search_providers` tool to find provider IDs. Do not pass it together with scan_id.", ), ) -> dict[str, Any]: """Get detailed requirement-level breakdown for a specific compliance framework. @@ -283,8 +283,8 @@ class ComplianceTools(BaseTool): - Use prowler_get_finding_details with these finding IDs for more details and remediation guidance Default behavior: - - Requires either scan_id OR provider_id - - With provider_id (no scan_id): Automatically finds the latest completed scan for that provider + - Requires exactly one of scan_id OR provider_id; providing both is rejected + - With provider_id: Automatically finds the latest completed scan for that provider - With scan_id: Uses that specific scan's compliance data - Only shows failed requirements with their associated failed finding IDs @@ -293,21 +293,22 @@ class ComplianceTools(BaseTool): 2. Use this tool with the compliance_id to see failed requirements and their finding IDs 3. Use prowler_get_finding_details with the finding IDs to get remediation guidance """ - # Validate that either scan_id or provider_id is provided + # Exactly one of the two: taking scan_id and ignoring provider_id would + # answer for whatever provider that scan belongs to, which is not + # necessarily the one the caller named. if not scan_id and not provider_id: - return { - "error": "Either scan_id or provider_id must be provided. Use prowler_search_providers to find provider IDs or prowler_list_scans to find scan IDs." - } + raise InvalidArgument( + "Either scan_id or provider_id must be provided. Use prowler_search_providers to find provider IDs or prowler_list_scans to find scan IDs." + ) + elif scan_id and provider_id: + raise InvalidArgument( + "Provide either scan_id or provider_id, not both. To get compliance data for a specific scan, use scan_id. To get data for the latest scan of a provider, use provider_id." + ) # Resolve provider_id to latest scan_id if needed resolved_scan_id = scan_id if not scan_id and provider_id: - try: - resolved_scan_id = await self._get_latest_scan_id_for_provider( - provider_id - ) - except ValueError as e: - return {"error": str(e)} + resolved_scan_id = await self._get_latest_scan_id_for_provider(provider_id) # Build params for requirements endpoint params: dict[str, Any] = { diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/finding_groups.py b/mcp_server/prowler_mcp_server/prowler_app/tools/finding_groups.py index 05adf8db2b..54bc3bcbcd 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/finding_groups.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/finding_groups.py @@ -6,8 +6,10 @@ This module provides read-only tools for finding group triage and drill-downs. from typing import Any, Literal from urllib.parse import quote +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.finding_groups import ( DetailedFindingGroup, FindingGroupResourcesListResponse, @@ -236,50 +238,46 @@ class FindingGroupsTools(BaseTool): prowler_get_finding_group_details for complete counters or prowler_list_finding_group_resources to drill into affected resources. """ - try: - self.api_client.validate_page_size(page_size) - date_range, params = self._base_date_params(date_from, date_to) - endpoint = self._group_endpoint(date_range) + self.api_client.validate_page_size(page_size) + date_range, params = self._base_date_params(date_from, date_to) + endpoint = self._group_endpoint(date_range) - self._apply_common_filters( - params, - provider, - provider_type, - provider_uid, - provider_alias, - region, - service, - resource_type, - resource_name, - resource_uid, - resource_group, - category, - check_id, - check_title, - severity, - status, - muted, - delta, - ) + self._apply_common_filters( + params, + provider, + provider_type, + provider_uid, + provider_alias, + region, + service, + resource_type, + resource_name, + resource_uid, + resource_group, + category, + check_id, + check_title, + severity, + status, + muted, + delta, + ) - params["filter[include_muted]"] = self._bool_value(include_muted) - params["page[size]"] = page_size - params["page[number]"] = page_number - params["fields[finding-groups]"] = GROUP_LIST_FIELDS - if sort: - params["sort"] = sort + params["filter[include_muted]"] = self._bool_value(include_muted) + params["page[size]"] = page_size + params["page[number]"] = page_number + params["fields[finding-groups]"] = GROUP_LIST_FIELDS + if sort: + params["sort"] = sort - clean_params = self.api_client.build_filter_params(params) - api_response = await self.api_client.get(endpoint, params=clean_params) - response = FindingGroupsListResponse.from_api_response(api_response) - return response.model_dump() - except Exception as e: - self.logger.error(f"Error listing finding groups: {e}") - return {"error": str(e), "status": "failed"} + clean_params = self.api_client.build_filter_params(params) + api_response = await self.api_client.get(endpoint, params=clean_params) + response = FindingGroupsListResponse.from_api_response(api_response) + return response.model_dump() async def get_finding_group_details( self, - check_id: str = Field( + check_id: NonBlankStr = Field( description="Public check ID that identifies the finding group. This is not a UUID." ), date_from: str | None = Field( @@ -297,39 +295,37 @@ class FindingGroupsTools(BaseTool): or historical data when dates are provided. Fully muted groups are included by default so accepted risk does not look like a missing group. """ - try: - date_range, params = self._base_date_params(date_from, date_to) - endpoint = self._group_endpoint(date_range) + date_range, params = self._base_date_params(date_from, date_to) + endpoint = self._group_endpoint(date_range) - params.update( - { - "filter[check_id]": check_id, - "filter[include_muted]": True, - "page[size]": 1, - "page[number]": 1, - "fields[finding-groups]": GROUP_DETAIL_FIELDS, - } + params.update( + { + "filter[check_id]": check_id, + "filter[include_muted]": True, + "page[size]": 1, + "page[number]": 1, + "fields[finding-groups]": GROUP_DETAIL_FIELDS, + } + ) + + clean_params = self.api_client.build_filter_params(params) + api_response = await self.api_client.get(endpoint, params=clean_params) + data = api_response.get("data", []) + + if not data: + # No `from`: this names the check and the tool that lists valid ones, + # neither of which the shared classifier can know. + raise ToolError( + f"No finding group exists for check '{check_id}' in this scan. Use " + "prowler_list_finding_groups to see the checks that have findings." ) - clean_params = self.api_client.build_filter_params(params) - api_response = await self.api_client.get(endpoint, params=clean_params) - data = api_response.get("data", []) - - if not data: - return { - "error": f"Finding group '{check_id}' not found.", - "status": "not_found", - } - - group = DetailedFindingGroup.from_api_response(data[0]) - return group.model_dump() - except Exception as e: - self.logger.error(f"Error getting finding group details: {e}") - return {"error": str(e), "status": "failed"} + group = DetailedFindingGroup.from_api_response(data[0]) + return group.model_dump() async def list_finding_group_resources( self, - check_id: str = Field( + check_id: NonBlankStr = Field( description="Public check ID that identifies the finding group. This is not a UUID." ), provider: list[str] = Field( @@ -426,45 +422,41 @@ class FindingGroupsTools(BaseTool): `finding_id`. Use `prowler_get_finding_details(finding_id)` to retrieve complete remediation guidance for a specific resource finding. """ - try: - self.api_client.validate_page_size(page_size) - date_range, params = self._base_date_params(date_from, date_to) - endpoint = self._resource_endpoint(check_id, date_range) + self.api_client.validate_page_size(page_size) + date_range, params = self._base_date_params(date_from, date_to) + endpoint = self._resource_endpoint(check_id, date_range) - if muted is None and not self._bool_value(include_muted): - muted = False + if muted is None and not self._bool_value(include_muted): + muted = False - self._apply_common_filters( - params, - provider, - provider_type, - provider_uid, - provider_alias, - region, - service, - resource_type, - resource_name, - resource_uid, - resource_group, - category, - [], - None, - severity, - status, - muted, - delta, - ) + self._apply_common_filters( + params, + provider, + provider_type, + provider_uid, + provider_alias, + region, + service, + resource_type, + resource_name, + resource_uid, + resource_group, + category, + [], + None, + severity, + status, + muted, + delta, + ) - params["page[size]"] = page_size - params["page[number]"] = page_number - params["fields[finding-group-resources]"] = RESOURCE_FIELDS - if sort: - params["sort"] = sort + params["page[size]"] = page_size + params["page[number]"] = page_number + params["fields[finding-group-resources]"] = RESOURCE_FIELDS + if sort: + params["sort"] = sort - clean_params = self.api_client.build_filter_params(params) - api_response = await self.api_client.get(endpoint, params=clean_params) - response = FindingGroupResourcesListResponse.from_api_response(api_response) - return response.model_dump() - except Exception as e: - self.logger.error(f"Error listing finding group resources: {e}") - return {"error": str(e), "status": "failed"} + clean_params = self.api_client.build_filter_params(params) + api_response = await self.api_client.get(endpoint, params=clean_params) + response = FindingGroupResourcesListResponse.from_api_response(api_response) + return response.model_dump() diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/findings.py b/mcp_server/prowler_mcp_server/prowler_app/tools/findings.py index b556101cab..860dfa806f 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/findings.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/findings.py @@ -8,6 +8,7 @@ from typing import Any, Literal from pydantic import Field +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.findings import ( DetailedFinding, FindingsListResponse, @@ -180,7 +181,7 @@ class FindingsTools(BaseTool): async def get_finding_details( self, - finding_id: str = Field( + finding_id: NonBlankStr = Field( description="UUID of the finding to retrieve (must be a valid UUID format, e.g., '019ac0d6-90d5-73e9-9acf-c22e256f1bac'). Returns an error if the finding ID is invalid or not found." ), ) -> dict[str, Any]: diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/integrations.py b/mcp_server/prowler_mcp_server/prowler_app/tools/integrations.py index d0aac0182a..f458a2ee5f 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/integrations.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/integrations.py @@ -9,8 +9,11 @@ This module provides tools for managing where Prowler sends its results, includi import json from typing import Any +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.errors import CredentialError, InvalidArgument +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.integrations import ( DetailedIntegration, IntegrationConnectionStatus, @@ -126,7 +129,7 @@ class IntegrationsTools(BaseTool): async def get_integration( self, - integration_id: str = Field( + integration_id: NonBlankStr = Field( description="UUID of the integration to retrieve. Must be a valid UUID format (e.g., '019ac0d6-90d5-73e9-9acf-c22e256f1bac'). Use prowler_list_integrations to find it." ), ) -> dict[str, Any]: @@ -157,7 +160,7 @@ class IntegrationsTools(BaseTool): async def create_amazon_s3_integration( self, - bucket_name: str = Field( + bucket_name: NonBlankStr = Field( description="Name of the S3 bucket where Prowler will upload the scan outputs (CSV, HTML, OCSF JSON and compliance reports)." ), output_directory: str = Field( @@ -168,15 +171,15 @@ class IntegrationsTools(BaseTool): default=[], description="Prowler UUIDs of the providers whose scan outputs are exported to this bucket. Use prowler_search_providers to find them. Leave empty to attach no provider yet.", ), - role_arn: str | None = Field( + role_arn: NonBlankStr | None = Field( default=None, description="ARN of the IAM role Prowler assumes to write to the bucket (e.g. 'arn:aws:iam::123456789012:role/ProwlerS3Integration'). Recommended over static keys.", ), - external_id: str | None = Field( + external_id: NonBlankStr | None = Field( default=None, description="External ID required by the trust policy of the assumed role. In Prowler Cloud this is the tenant ID.", ), - role_session_name: str | None = Field( + role_session_name: NonBlankStr | None = Field( default=None, description="Identifier for the role session, useful to track it in AWS logs. Only letters, digits and the characters =,.@_- are allowed.", ), @@ -184,15 +187,15 @@ class IntegrationsTools(BaseTool): default=3600, description="Duration of the assumed role session in seconds. Must be between 900 and 43200. Defaults to 3600 when omitted.", ), - aws_access_key_id: str | None = Field( + aws_access_key_id: NonBlankStr | None = Field( default=None, description="AWS access key ID. Only needed when the Prowler deployment has no ambient AWS credentials.", ), - aws_secret_access_key: str | None = Field( + aws_secret_access_key: NonBlankStr | None = Field( default=None, description="AWS secret access key. Required when 'aws_access_key_id' is provided.", ), - aws_session_token: str | None = Field( + aws_session_token: NonBlankStr | None = Field( default=None, description="AWS session token, only for temporary credentials.", ), @@ -244,34 +247,30 @@ class IntegrationsTools(BaseTool): """ self.logger.info(f"Creating Amazon S3 integration for bucket {bucket_name}...") - try: - credentials = self._build_aws_credentials( - role_arn=role_arn, - external_id=external_id, - role_session_name=role_session_name, - session_duration=session_duration, - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - ) + credentials = self._build_aws_credentials( + role_arn=role_arn, + external_id=external_id, + role_session_name=role_session_name, + session_duration=session_duration, + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + aws_session_token=aws_session_token, + ) - return await self._create_integration( - integration_type="amazon_s3", - configuration={ - "bucket_name": bucket_name, - "output_directory": output_directory, - }, - credentials=credentials, - provider_ids=provider_ids, - enabled=enabled, - ) - except Exception as e: - self.logger.error(f"Amazon S3 integration creation failed: {e}") - return {"error": str(e), "status": "failed"} + return await self._create_integration( + integration_type="amazon_s3", + configuration={ + "bucket_name": bucket_name, + "output_directory": output_directory, + }, + credentials=credentials, + provider_ids=provider_ids, + enabled=enabled, + ) async def create_aws_security_hub_integration( self, - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="Prowler UUID of the AWS provider whose findings are sent to Security Hub. It must be an AWS provider, and it can only have one Security Hub integration. Use prowler_search_providers with provider_type=['aws'] to find it." ), send_only_fails: bool = Field( @@ -282,15 +281,15 @@ class IntegrationsTools(BaseTool): default=False, description="When true, findings that are no longer present in the latest scan are archived in Security Hub.", ), - role_arn: str | None = Field( + role_arn: NonBlankStr | None = Field( default=None, description="ARN of a dedicated IAM role Prowler assumes to write to Security Hub. Leave every credential parameter empty to reuse the credentials already stored for the provider, which is the recommended setup.", ), - external_id: str | None = Field( + external_id: NonBlankStr | None = Field( default=None, description="External ID required by the trust policy of the assumed role.", ), - role_session_name: str | None = Field( + role_session_name: NonBlankStr | None = Field( default=None, description="Identifier for the role session, useful to track it in AWS logs. Only letters, digits and the characters =,.@_- are allowed.", ), @@ -298,14 +297,14 @@ class IntegrationsTools(BaseTool): default=None, description="Duration of the assumed role session in seconds. Must be between 900 and 43200. Defaults to 3600 when omitted.", ), - aws_access_key_id: str | None = Field( + aws_access_key_id: NonBlankStr | None = Field( default=None, description="AWS access key ID for dedicated credentials." ), - aws_secret_access_key: str | None = Field( + aws_secret_access_key: NonBlankStr | None = Field( default=None, description="AWS secret access key. Required when 'aws_access_key_id' is provided.", ), - aws_session_token: str | None = Field( + aws_session_token: NonBlankStr | None = Field( default=None, description="AWS session token, only for temporary credentials.", ), @@ -344,40 +343,36 @@ class IntegrationsTools(BaseTool): f"Creating AWS Security Hub integration for provider {provider_id}..." ) - try: - credentials = self._build_aws_credentials( - role_arn=role_arn, - external_id=external_id, - role_session_name=role_session_name, - session_duration=session_duration, - aws_access_key_id=aws_access_key_id, - aws_secret_access_key=aws_secret_access_key, - aws_session_token=aws_session_token, - ) + credentials = self._build_aws_credentials( + role_arn=role_arn, + external_id=external_id, + role_session_name=role_session_name, + session_duration=session_duration, + aws_access_key_id=aws_access_key_id, + aws_secret_access_key=aws_secret_access_key, + aws_session_token=aws_session_token, + ) - return await self._create_integration( - integration_type="aws_security_hub", - configuration={ - "send_only_fails": send_only_fails, - "archive_previous_findings": archive_previous_findings, - }, - credentials=credentials, - provider_ids=[provider_id], - enabled=enabled, - ) - except Exception as e: - self.logger.error(f"AWS Security Hub integration creation failed: {e}") - return {"error": str(e), "status": "failed"} + return await self._create_integration( + integration_type="aws_security_hub", + configuration={ + "send_only_fails": send_only_fails, + "archive_previous_findings": archive_previous_findings, + }, + credentials=credentials, + provider_ids=[provider_id], + enabled=enabled, + ) async def create_jira_integration( self, - domain: str = Field( + domain: NonBlankStr = Field( description="Atlassian site name, without the '.atlassian.net' suffix. For the site 'https://acme.atlassian.net' the value is 'acme'. Full URLs are accepted and normalized automatically." ), - user_mail: str = Field( + user_mail: NonBlankStr = Field( description="Email address of the Atlassian account that owns the API token." ), - api_token: str = Field( + api_token: NonBlankStr = Field( description="Atlassian API token, created from the account settings. It needs the 'read:jira-user', 'read:jira-work' and 'write:jira-work' scopes." ), enabled: bool = Field( @@ -416,31 +411,25 @@ class IntegrationsTools(BaseTool): 3. Use prowler_get_jira_issue_types with that project key to pick an issue type 4. Use prowler_send_findings_to_jira to create the work items """ - try: - normalized_domain = self._normalize_atlassian_domain(domain) - self.logger.info( - f"Creating Jira integration for domain {normalized_domain}..." - ) + normalized_domain = self._normalize_atlassian_domain(domain) + self.logger.info(f"Creating Jira integration for domain {normalized_domain}...") - return await self._create_integration( - integration_type="jira", - # Jira rejects any configuration in the payload, the API generates it - configuration={}, - credentials={ - "domain": normalized_domain, - "user_mail": user_mail, - "api_token": api_token, - }, - provider_ids=[], - enabled=enabled, - ) - except Exception as e: - self.logger.error(f"Jira integration creation failed: {e}") - return {"error": str(e), "status": "failed"} + return await self._create_integration( + integration_type="jira", + # Jira rejects any configuration in the payload, the API generates it + configuration={}, + credentials={ + "domain": normalized_domain, + "user_mail": user_mail, + "api_token": api_token, + }, + provider_ids=[], + enabled=enabled, + ) async def update_integration( self, - integration_id: str = Field( + integration_id: NonBlankStr = Field( description="UUID of the integration to update. Use prowler_list_integrations to find it." ), enabled: bool | None = Field( @@ -494,96 +483,86 @@ class IntegrationsTools(BaseTool): """ self.logger.info(f"Updating integration {integration_id}...") - try: - current = DetailedIntegration.from_api_response( - await self._get_integration_raw(integration_id) - ) - integration_type = current.integration_type + current = DetailedIntegration.from_api_response( + await self._get_integration_raw(integration_id) + ) + integration_type = current.integration_type - if provider_ids is not None: - if integration_type == "jira": - raise ValueError( - "Jira integrations are tenant-wide and cannot be attached to providers." - ) - if integration_type == "aws_security_hub" and len(provider_ids) != 1: - raise ValueError( - "AWS Security Hub integrations must stay attached to exactly one AWS " - f"provider, got {len(provider_ids)}. Pass a single provider ID, or use " - "prowler_delete_integration to stop sending findings to Security Hub." - ) - - attributes: dict[str, Any] = {} - if enabled is not None: - attributes["enabled"] = enabled - - if credentials is not None: - attributes["credentials"] = self._validate_credentials( - integration_type, self._as_dict(credentials, "credentials") + if provider_ids is not None: + if integration_type == "jira": + raise InvalidArgument( + "Jira integrations are tenant-wide and cannot be attached to providers." + ) + if integration_type == "aws_security_hub" and len(provider_ids) != 1: + raise InvalidArgument( + "AWS Security Hub integrations must stay attached to exactly one AWS " + f"provider, got {len(provider_ids)}. Pass a single provider ID, or use " + "prowler_delete_integration to stop sending findings to Security Hub." ) - if configuration is not None: - if integration_type == "jira": - raise ValueError( - "Jira integrations do not accept a configuration: it is generated by Prowler. " - "Update the credentials instead, or run prowler_test_integration_connection to " - "refresh the available projects and issue types." - ) - merged = dict(current.configuration) - merged.update(self._as_dict(configuration, "configuration")) - # Server-owned, the API repopulates it from the connection check - merged.pop("regions", None) - merged.pop("enabled_regions", None) - attributes["configuration"] = merged + attributes: dict[str, Any] = {} + if enabled is not None: + attributes["enabled"] = enabled - if not attributes and provider_ids is None: - self.logger.info("No changes provided, returning the current state") - return current.model_dump() + if credentials is not None: + attributes["credentials"] = self._validate_credentials( + integration_type, self._as_dict(credentials, "credentials") + ) - update_body: dict[str, Any] = { - "data": { - "type": "integrations", - "id": integration_id, - "attributes": attributes, - } + if configuration is not None: + if integration_type == "jira": + raise InvalidArgument( + "Jira integrations do not accept a configuration: it is generated by Prowler. " + "Update the credentials instead, or run prowler_test_integration_connection to " + "refresh the available projects and issue types." + ) + merged = dict(current.configuration) + merged.update(self._as_dict(configuration, "configuration")) + # Server-owned, the API repopulates it from the connection check + merged.pop("regions", None) + merged.pop("enabled_regions", None) + attributes["configuration"] = merged + + if not attributes and provider_ids is None: + self.logger.info("No changes provided, returning the current state") + return current.model_dump() + + update_body: dict[str, Any] = { + "data": { + "type": "integrations", + "id": integration_id, + "attributes": attributes, } - if provider_ids is not None: - update_body["data"]["relationships"] = _providers_relationship( - provider_ids - ) + } + if provider_ids is not None: + update_body["data"]["relationships"] = _providers_relationship(provider_ids) - await self.api_client.patch( - f"/integrations/{integration_id}", json_data=update_body - ) + await self.api_client.patch( + f"/integrations/{integration_id}", json_data=update_body + ) - # A different provider means different effective credentials and different - # discovered configuration, so the stored connection state is stale too - providers_changed = provider_ids is not None and set(provider_ids) != set( - current.provider_ids - ) - recheck_connection = ( - credentials is not None - or configuration is not None - or providers_changed - ) - connection_status = ( - await self._test_connection(integration_id) - if recheck_connection - else None - ) + # A different provider means different effective credentials and different + # discovered configuration, so the stored connection state is stale too + providers_changed = provider_ids is not None and set(provider_ids) != set( + current.provider_ids + ) + recheck_connection = ( + credentials is not None or configuration is not None or providers_changed + ) + connection_status = ( + await self._test_connection(integration_id) if recheck_connection else None + ) - updated = await self._get_integration_raw(integration_id) - if connection_status is not None: - return IntegrationConnectionStatus.create( - updated, connection_status - ).model_dump() - return DetailedIntegration.from_api_response(updated).model_dump() - except Exception as e: - self.logger.error(f"Integration update failed: {e}") - return {"error": str(e), "status": "failed"} + updated = await self._get_integration_raw(integration_id) + if connection_status is not None: + return IntegrationConnectionStatus.create( + updated, connection_status + ).model_dump() + return DetailedIntegration.from_api_response(updated).model_dump() async def delete_integration( self, - integration_id: str = Field( + integration_id: NonBlankStr = Field( description="UUID of the integration to permanently remove. Use prowler_list_integrations to find it." ), ) -> dict[str, Any]: @@ -606,22 +585,15 @@ class IntegrationsTools(BaseTool): """ self.logger.info(f"Deleting integration {integration_id}...") - try: - await self.api_client.delete(f"/integrations/{integration_id}") - return { - "deleted": True, - "message": f"Integration {integration_id} deleted successfully", - } - except Exception as e: - self.logger.error(f"Integration deletion failed: {e}") - return { - "deleted": False, - "message": f"Integration {integration_id} deletion failed: {str(e)}", - } + await self.api_client.delete(f"/integrations/{integration_id}") + # No `deleted` flag: an integration that was not deleted leaves this tool + # as an error, so the flag could only ever be True and a reader branching + # on it would be looking for a shape that does not exist. + return {"message": f"Integration {integration_id} deleted successfully"} async def test_integration_connection( self, - integration_id: str = Field( + integration_id: NonBlankStr = Field( description="UUID of the integration to check. Use prowler_list_integrations to find it." ), ) -> dict[str, Any]: @@ -654,10 +626,10 @@ class IntegrationsTools(BaseTool): async def get_jira_issue_types( self, - integration_id: str = Field( + integration_id: NonBlankStr = Field( description="UUID of the Jira integration. Use prowler_list_integrations with integration_type=['jira'] to find it." ), - project_key: str = Field( + project_key: NonBlankStr = Field( description="Key of the Jira project to read the issue types from (e.g. 'PROJ'). It must be one of the keys in the 'projects' mapping of the integration configuration." ), ) -> dict[str, Any]: @@ -692,13 +664,13 @@ class IntegrationsTools(BaseTool): async def send_findings_to_jira( self, - integration_id: str = Field( + integration_id: NonBlankStr = Field( description="UUID of the Jira integration to send the findings through. It must be enabled." ), - project_key: str = Field( + project_key: NonBlankStr = Field( description="Key of the Jira project the work items are created in (e.g. 'PROJ'). It must be one of the keys in the 'projects' mapping of the integration configuration." ), - issue_type: str = Field( + issue_type: NonBlankStr = Field( description="Jira issue type for the created work items (e.g. 'Task', 'Bug', 'Story'). It must be one of the values returned by prowler_get_jira_issue_types for this project." ), finding_ids: list[str] = Field( @@ -783,20 +755,26 @@ class IntegrationsTools(BaseTool): return self._jira_dispatch_unknown( task_id=None, error=( - f"the request that starts the dispatch failed on the server: {e} " + "the request that starts the dispatch failed on Prowler's side. " "It may have been queued anyway." ), ) self.logger.error(f"Jira dispatch was rejected by Prowler: {e}") return self._jira_dispatch_rejected(str(e)) + except CredentialError: + # Authentication happens before the request goes out, so nothing was + # queued. It is raised rather than reported as a dispatch outcome: + # there is no partial state to describe, and the shared classifier + # says what has to be fixed, which no retry of this call can. + raise except Exception as e: # No answer came back, so the request may still have been accepted self.logger.error(f"Jira dispatch could not be started: {e}") return self._jira_dispatch_unknown( task_id=None, error=( - f"the request that starts the dispatch got no answer: {e} " + "the request that starts the dispatch got no answer. " "It may have been accepted anyway." ), ) @@ -866,7 +844,7 @@ class IntegrationsTools(BaseTool): normalized = normalized.removesuffix(".atlassian.net") if not normalized: - raise ValueError( + raise InvalidArgument( f"Invalid Jira domain: {domain}. Provide the Atlassian site name, for example " "'acme' for the site 'https://acme.atlassian.net'." ) @@ -890,7 +868,7 @@ class IntegrationsTools(BaseTool): if not isinstance(credentials.get(key), str) or not credentials[key].strip() ] if missing: - raise ValueError( + raise InvalidArgument( "Jira credentials are replaced as a whole, so 'domain', 'user_mail' and " f"'api_token' are all required. Missing or empty: {', '.join(missing)}. " "Sending an incomplete object would destroy the stored credentials and break " @@ -908,29 +886,33 @@ class IntegrationsTools(BaseTool): try: value = json.loads(value) except json.JSONDecodeError as e: - raise ValueError(f"Invalid JSON for {param_name}: {e}") + raise InvalidArgument(f"Invalid JSON for {param_name}: {e}") from e if not isinstance(value, dict): - raise ValueError(f"{param_name} must be a JSON object.") + raise InvalidArgument(f"{param_name} must be a JSON object.") return value async def _get_integration_raw(self, integration_id: str) -> dict[str, Any]: """Fetch the raw JSON:API resource of an integration. Raises: - ValueError: If the payload does not contain a usable integration resource + ToolError: If the payload does not contain a usable integration resource. + Raised without a ``from`` clause because these messages name the + integration and the tool that lists valid IDs, and the two cases + are reported differently: a missing resource is the caller's + mistake, a resource without attributes is the API's. """ response = await self.api_client.get(f"/integrations/{integration_id}") integration = response.get("data") if not isinstance(integration, dict) or not integration.get("id"): - raise ValueError( + raise ToolError( f"Integration {integration_id} was not found. Use prowler_list_integrations " "to get a valid integration ID." ) if not isinstance(integration.get("attributes"), dict): - raise ValueError( + raise ToolError( f"Prowler returned integration {integration_id} without its attributes, so " "its state cannot be read." ) @@ -970,7 +952,9 @@ class IntegrationsTools(BaseTool): integration_id = api_response.get("data", {}).get("id") if not integration_id: - raise ValueError( + # The integration may well exist, so this must not read as "nothing + # happened" and invite a duplicate. + raise ToolError( "Prowler accepted the integration creation but did not return its ID, so the " "connection could not be checked. Use prowler_list_integrations to see whether " "the integration exists before creating it again." @@ -981,11 +965,17 @@ class IntegrationsTools(BaseTool): try: integration = await self._get_integration_raw(integration_id) except Exception as e: - # The integration exists, so surface its ID instead of a plain read failure - raise ValueError( - f"Integration {integration_id} was created, but reading its state failed: {e} " + # The integration exists, so surface its ID instead of a plain read + # failure. No `from` clause: a cause would let the shared classifier + # replace this with a sentence that does not mention the ID. The + # failure text stays in the log, where the classifier would keep it. + self.logger.error( + f"Integration {integration_id} could not be read back: {e}" + ) + raise ToolError( + f"Integration {integration_id} was created, but reading its state failed. " "Use prowler_get_integration with that ID to check it." - ) from e + ) return IntegrationConnectionStatus.create( integration, connection_status @@ -1030,7 +1020,7 @@ class IntegrationsTools(BaseTool): return { "connected": None, "error": ( - f"The connection check could not be completed: {e} This says nothing " + "The connection check could not be completed. This says nothing " "about the stored credentials, run prowler_test_integration_connection " "to check them again." ), diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/muting.py b/mcp_server/prowler_mcp_server/prowler_app/tools/muting.py index 37e1504165..69a5f8884c 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/muting.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/muting.py @@ -8,8 +8,11 @@ This module provides tools for managing finding muting in Prowler, including: import json from typing import Any +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.errors import InvalidArgument +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.muting import ( DetailedMuteRule, MutelistResponse, @@ -28,10 +31,31 @@ class MutingTools(BaseTool): # ===== MUTELIST TOOLS ===== + async def _get_mutelist_raw(self) -> dict[str, Any] | None: + """Return the tenant's mutelist, or None when it has none. + + Returns: + The mutelist configuration, or None when the tenant has none + """ + params = { + "filter[processor_type]": "mutelist", + "fields[processors]": "processor_type,configuration,inserted_at,updated_at", + } + + clean_params = self.api_client.build_filter_params(params) + api_response = await self.api_client.get("/processors", params=clean_params) + + data = api_response.get("data", []) + if not data: + return None + + # Only one mutelist can exist per tenant + return MutelistResponse.from_api_response(data[0]).model_dump() + async def get_mutelist(self) -> dict[str, Any]: """Retrieve the current mutelist configuration for the tenant. - IMPORTANT: Only one mutelist can exist per tenant. Returns an error message if no mutelist exists. + IMPORTANT: Only one mutelist can exist per tenant. Fails with a message saying so if no mutelist exists. For detailed information about mutelist structure and configuration, search Prowler documentation using prowler_docs_search tool available in this MCP Server. @@ -47,26 +71,15 @@ class MutingTools(BaseTool): """ self.logger.info("Retrieving mutelist configuration...") - # Query processors filtered by type=mutelist - params = { - "filter[processor_type]": "mutelist", - "fields[processors]": "processor_type,configuration,inserted_at,updated_at", - } - - clean_params = self.api_client.build_filter_params(params) - api_response = await self.api_client.get("/processors", params=clean_params) - - data = api_response.get("data", []) - - if len(data) == 0: - return { - "error": "No mutelist found", - "message": "No mutelist configuration exists for this tenant. Use prowler_set_mutelist to create one.", - } - - # Return the first (and only) mutelist - mutelist = MutelistResponse.from_api_response(data[0]) - return mutelist.model_dump() + mutelist = await self._get_mutelist_raw() + if mutelist is None: + # No `from`: this names the tool that creates one, which the shared + # classifier cannot know. + raise ToolError( + "No mutelist configuration exists for this tenant. Use " + "prowler_set_mutelist to create one." + ) + return mutelist async def set_mutelist( self, @@ -128,9 +141,9 @@ Structure: configuration = json.loads(configuration) # Check if mutelist already exists - existing_mutelist = await self.get_mutelist() + existing_mutelist = await self._get_mutelist_raw() - if "error" in existing_mutelist: + if existing_mutelist is None: # Create new mutelist self.logger.info("Creating new mutelist...") create_body = { @@ -183,21 +196,22 @@ Structure: self.logger.info("Deleting mutelist configuration...") # Get existing mutelist - existing_mutelist = await self.get_mutelist() + existing_mutelist = await self._get_mutelist_raw() - if "error" in existing_mutelist: - return { - "success": False, - "message": "No mutelist found to delete", - } + if existing_mutelist is None: + raise ToolError( + "There is no mutelist configuration to delete. Use " + "prowler_get_mutelist to confirm the current state." + ) # Delete the mutelist mutelist_id = existing_mutelist["id"] await self.api_client.delete(f"/processors/{mutelist_id}") + # No success flag: a deletion that did not happen leaves this tool as an + # error, so there is no second shape for one to distinguish. return { - "success": True, - "message": "Mutelist deleted successfully", + "message": "Mutelist deleted successfully. Findings it had muted stay muted." } # ===== MUTE RULES TOOLS ===== @@ -268,7 +282,7 @@ Structure: elif enabled.lower() == "false": params["filter[enabled]"] = False else: - raise ValueError( + raise InvalidArgument( f"Invalid enabled value: {enabled}. Valid values are True, False, 'true', 'false' or None." ) if search: @@ -282,7 +296,7 @@ Structure: async def get_mute_rule( self, - rule_id: str = Field( + rule_id: NonBlankStr = Field( description="UUID of the mute rule to retrieve. Must be a valid UUID format (e.g., '019ac0d6-90d5-73e9-9acf-c22e256f1bac')." ), ) -> dict[str, Any]: @@ -316,10 +330,10 @@ Structure: async def create_mute_rule( self, - name: str = Field( + name: NonBlankStr = Field( description="Name for the mute rule. Should be descriptive and meaningful (e.g., 'Dev S3 Public Access', 'Test Environment IMDSv1')." ), - reason: str = Field( + reason: NonBlankStr = Field( description="Reason for muting these findings. Document why this security issue is acceptable or intentional (e.g., 'Development environment with controlled access', 'Legacy application requires IMDSv1')." ), finding_ids: list[str] = Field( @@ -367,14 +381,14 @@ Structure: async def update_mute_rule( self, - rule_id: str = Field( + rule_id: NonBlankStr = Field( description="UUID of the mute rule to update. Must be a valid UUID format." ), - name: str | None = Field( + name: NonBlankStr | None = Field( default=None, description="New name for the rule. If not specified, name remains unchanged.", ), - reason: str | None = Field( + reason: NonBlankStr | None = Field( default=None, description="New reason for the rule. If not specified, reason remains unchanged.", ), @@ -435,7 +449,7 @@ Structure: async def delete_mute_rule( self, - rule_id: str = Field( + rule_id: NonBlankStr = Field( description="UUID of the mute rule to delete. Must be a valid UUID format." ), ) -> dict[str, Any]: @@ -457,15 +471,18 @@ Structure: """ self.logger.info(f"Deleting mute rule {rule_id}...") - result = await self.api_client.delete(f"/mute-rules/{rule_id}") + # A deletion that did not happen answers with an error status, which + # leaves this tool as an error. Reaching this line means Prowler accepted + # it, whether it answered 204 with no body or 200 with the deleted + # resource, so there is no second outcome to report: the previous + # "Failed to delete mute rule" fired on the shape of the answer rather + # than on anything having gone wrong, and said nothing a caller could act + # on. + await self.api_client.delete(f"/mute-rules/{rule_id}") - if result.get("success"): - return { - "success": True, - "message": "Mute rule deleted successfully", - } - else: - return { - "success": False, - "message": "Failed to delete mute rule", - } + return { + "message": ( + f"Mute rule {rule_id} deleted successfully. The findings it muted stay " + "muted." + ) + } diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/providers.py b/mcp_server/prowler_mcp_server/prowler_app/tools/providers.py index 3ba417d677..542289c652 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/providers.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/providers.py @@ -6,10 +6,14 @@ including searching, connecting, and deleting providers. from typing import Any +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.errors import InvalidArgument +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.providers import ( ProviderConnectionStatus, + ProviderDeletionResult, ProvidersListResponse, ) from prowler_mcp_server.prowler_app.tools.base import BaseTool @@ -95,7 +99,7 @@ class ProvidersTools(BaseTool): elif connected.lower() == "false": params["filter[connected]"] = False else: - raise ValueError( + raise InvalidArgument( f"Invalid connected value: {connected}. Valid values are True, False, 'true', 'false' or None." ) @@ -128,13 +132,13 @@ class ProvidersTools(BaseTool): async def connect_provider( self, - provider_uid: str = Field( + provider_uid: NonBlankStr = Field( description="Provider's unique identifier. For supported UID provider formats, please refer to Prowler Hub/Prowler Documentation that you can also find in form of tools in this MCP Server" ), - provider_type: str = Field( + provider_type: NonBlankStr = Field( description="Type of provider to be scanned with Prowler. Valid values include: 'aws', 'azure', 'gcp', 'kubernetes'... For more valid values, please refer to Prowler Hub/Prowler Documentation that you can also find in form of tools in this MCP Server." ), - alias: str | None = Field( + alias: NonBlankStr | None = Field( default=None, description="Human-friendly name for this provider. Optional but recommended for easy identification. Use descriptive names to distinguish multiple accounts of the same type.", ), @@ -291,7 +295,7 @@ class ProvidersTools(BaseTool): async def delete_provider( self, - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the provider to permanently remove, generated when the provider was registered in the system. Use `prowler_search_providers` tool to find the provider_id if you only know the alias or the provider's own identifier (provider_uid)" ), ) -> dict[str, Any]: @@ -300,33 +304,120 @@ class ProvidersTools(BaseTool): WARNING: This is a destructive operation that cannot be undone. The provider will need to be re-added with prowler_connect_provider if you want to scan it again. - The tool always returns the deletion status and message. + Prowler removes the provider and everything attached to it (its scans, findings and + resources) in a background task, so a large provider can take longer than the time + this tool waits for it. + + The result includes: + - status: 'deleted' when Prowler finished removing the provider, 'in_progress' when + the deletion was accepted and is still running + - task_id: the background task, present when the deletion was still running + + NEVER send the deletion again while status='in_progress'. Use prowler_search_providers + to check whether the provider is gone. """ self.logger.info(f"Deleting provider {provider_id}...") - try: - # Initiate the deletion task - task_response = await self.api_client.delete(f"/providers/{provider_id}") - task_id = task_response.get("data", {}).get("id") - # Poll until task completes (with 60 second timeout) + # A failure of the request itself is left to the shared classifier: the + # deletion never started, so there is no partial state to describe. + task_response = await self.api_client.delete(f"/providers/{provider_id}") + task_id = task_response.get("data", {}).get("id") + + if not task_id: + # The deletion may well be running, so this must not read as "nothing + # happened". No `from` clause: this names the provider and the tool + # that checks it, neither of which the shared classifier can know. + raise ToolError( + f"Prowler accepted the deletion of provider {provider_id} but did not " + "return the ID of the background task, so its outcome cannot be checked. " + "Use prowler_search_providers to see whether the provider is still there " + "before sending the deletion again." + ) + + try: await self.api_client.poll_task_until_complete( task_id=task_id, timeout=60, poll_interval=1.0 ) - - # If we reach here, the task completed successfully - return { - "deleted": True, - "message": f"Provider {provider_id} deleted successfully", - } except Exception as e: - self.logger.error(f"Provider deletion failed: {e}") - return { - "deleted": False, - "message": f"Provider {provider_id} deletion failed: {str(e)}", - } + self.logger.error(f"Provider deletion did not complete cleanly: {e}") + return await self._provider_deletion_fallback(provider_id, task_id) + + return ProviderDeletionResult( + status="deleted", + message=f"Provider {provider_id} deleted successfully", + ).model_dump() # Private helper methods + async def _provider_deletion_fallback( + self, provider_id: str, task_id: str + ) -> dict[str, Any]: + """Report a provider deletion whose polling did not end on a completed task. + + Running out of the polling window is not a failure: Prowler removes the + provider together with its scans, findings and resources, which outlives + 60 seconds on a large account. The deletion was accepted and is still + going, so calling it failed would be wrong twice over -- it is not, and + it invites a retry of a destructive call already in flight. + + The task is read once more here, because polling gives up on the clock + rather than on the task: a deletion that finished just after the last + poll is a finished deletion and is reported as one. + + Only a task that actually stopped is an error, and it is raised rather + than returned, because then the provider is still there. + + Raises: + ToolError: If the deletion task ended without deleting the provider. + Raised without a ``from`` clause because the message names what + was left behind, which the shared classifier cannot know. + """ + state = None + try: + task = await self.api_client.get(f"/tasks/{task_id}") + state = task.get("data", {}).get("attributes", {}).get("state") + except Exception as e: + self.logger.error(f"Could not read the state of task {task_id}: {e}") + + if state == "completed": + # The deletion outran the polling window by a moment, not by more. + return ProviderDeletionResult( + status="deleted", + message=f"Provider {provider_id} deleted successfully", + ).model_dump() + + if state in ("failed", "cancelled"): + # The failure that got us here is logged, not relayed: it carries + # upstream text, and the classifier masks exactly this kind of + # message when a tool does not write it itself. + raise ToolError( + f"The task deleting provider {provider_id} ended as '{state}', so the " + "provider was not deleted. Prowler removes a provider together with its " + "scans, findings and resources, so part of that may already be gone. Use " + "prowler_search_providers to check the current state." + ) + + if state is None: + message = ( + f"The deletion of provider {provider_id} was accepted, but its progress " + "could not be read, so whether it finished is unknown. Do not " + "send the deletion again. Use prowler_search_providers to check whether " + "the provider is gone." + ) + else: + message = ( + f"The deletion of provider {provider_id} was accepted and is still " + f"running (task state '{state}'), which is normal for a provider with " + "many scans and findings. Do not send the deletion again. Use " + "prowler_search_providers to check whether it is gone." + ) + + return ProviderDeletionResult( + status="in_progress", + task_id=task_id, + message=message, + ).model_dump() + async def _check_provider_exists(self, provider_uid: str) -> str | None: """Check if a provider already exists by its UID. @@ -357,7 +448,7 @@ class ProvidersTools(BaseTool): return prowler_provider_id else: # Multiple providers with the same UID is a data integrity issue - raise Exception( + raise ToolError( f"Data integrity error: Found {len(providers)} providers with UID '{provider_uid}'. " f"Each provider UID should be unique. Please contact support or manually clean up duplicate providers." ) @@ -392,7 +483,11 @@ class ProvidersTools(BaseTool): provider_id = await self._check_provider_exists(provider_uid) if provider_id is None: - raise Exception(f"Provider {provider_uid} creation failed") + raise ToolError( + f"Prowler accepted the creation of provider {provider_uid} but the " + "provider cannot be found afterwards. Use prowler_search_providers to " + "check whether it exists before creating it again." + ) return provider_id async def _update_provider_alias( @@ -418,7 +513,10 @@ class ProvidersTools(BaseTool): f"/providers/{prowler_provider_id}", json_data=update_body ) if result.get("data", {}).get("attributes", {}).get("alias") != alias: - raise Exception(f"Provider {prowler_provider_id} alias update failed") + raise ToolError( + f"Provider {prowler_provider_id} exists, but its alias was not updated. " + "Use prowler_search_providers to read its current alias." + ) def _determine_secret_type(self, credentials: dict[str, Any]) -> str: """Determine the secret type from credentials structure. @@ -443,29 +541,32 @@ class ProvidersTools(BaseTool): prowler_provider_id: The Prowler-generated provider ID Returns: - The secret ID if exists, None otherwise - """ - try: - response = await self.api_client.get( - "/providers/secrets", - params={"filter[provider]": prowler_provider_id}, - ) - secrets = response.get("data", []) + The secret ID if the provider has one, None if it has none - if len(secrets) > 0: - secret_id = secrets[0].get("id") - self.logger.info( - f"Found existing secret {secret_id} for provider {prowler_provider_id}" - ) - return secret_id - else: - self.logger.info( - f"No existing secret found for provider {prowler_provider_id}" - ) - return None - except Exception as e: - self.logger.error(f"Error checking for existing secret: {e}") - return None + Raises: + Exception: If the lookup itself failed, so that "no secret" is never + reported for a provider whose secret could not be read + """ + # A failure here is not swallowed into None. None means "this provider has + # no secret", which sends `_store_credentials` down the create branch, and + # a provider holds at most one secret: creating a second one is refused, + # and the caller would be told its credentials were rejected when all that + # actually failed was this read. + response = await self.api_client.get( + "/providers/secrets", + params={"filter[provider]": prowler_provider_id}, + ) + secrets = response.get("data", []) + + if len(secrets) > 0: + secret_id = secrets[0].get("id") + self.logger.info( + f"Found existing secret {secret_id} for provider {prowler_provider_id}" + ) + return secret_id + + self.logger.info(f"No existing secret found for provider {prowler_provider_id}") + return None async def _get_secret_type(self, secret_id: str) -> str | None: """Get the secret type for a given secret ID. @@ -573,13 +674,24 @@ class ProvidersTools(BaseTool): raise async def _test_connection(self, prowler_provider_id: str) -> dict[str, Any]: - """Test connection to a provider. + """Test connection to a provider and wait for the result. + + A test that could not be run is reported as 'connected: None', which + `ProviderConnectionStatus` renders as 'not_tested', rather than as a + failure. Credentials that do not work come back as a completed task + carrying 'connected: False', so an exception here never describes them: + it means this server could not get the test run at all -- an expired + Prowler credential, a rate limit, a test that outlived the timeout. + Reporting that as 'failed' would blame the provider's credentials for + something they did not cause, and send the caller off to fix a working + role. Args: prowler_provider_id: The Prowler-generated provider ID Returns: - Connection status dictionary with 'connected' boolean and optional 'error' message + Connection status dictionary with a 'connected' boolean or None, and + an optional 'error' message """ self.logger.info(f"Testing connection for provider {prowler_provider_id}...") try: @@ -589,6 +701,11 @@ class ProvidersTools(BaseTool): ) task_id = task_response.get("data", {}).get("id") + if not task_id: + raise ValueError( + "Prowler did not return the ID of the connection test task." + ) + # Poll until task completes (with 60 second timeout) completed_task = await self.api_client.poll_task_until_complete( task_id=task_id, timeout=60, poll_interval=1.0 @@ -596,13 +713,26 @@ class ProvidersTools(BaseTool): # Extract the result from the completed task task_result = ( - completed_task.get("data", {}).get("attributes", {}).get("result", {}) + completed_task.get("data", {}).get("attributes", {}).get("result") ) + if not isinstance(task_result, dict): + raise ValueError( + "The connection test task completed without reporting a result." + ) + return task_result except Exception as e: - self.logger.error(f"Connection test failed: {e}") - return {"connected": False, "error": str(e)} + self.logger.error(f"Connection test could not be completed: {e}") + return { + "connected": None, + "error": ( + "The connection test could not be completed. This says nothing " + "about the provider's credentials, they were never tested. Use " + "prowler_search_providers to read the connection state Prowler has " + "stored for this provider." + ), + } async def _get_final_provider_state( self, prowler_provider_id: str 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 88fcca25ae..96a24fb4b2 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 pydantic import Field +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.resources import ( DetailedResource, ResourceEventsResponse, @@ -176,7 +177,7 @@ class ResourcesTools(BaseTool): async def get_resource( self, - resource_id: str = Field( + resource_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the resource to retrieve, generated when the resource was discovered in the system. Use `prowler_list_resources` tool to find the right ID" ), ) -> dict[str, Any]: @@ -347,7 +348,7 @@ class ResourcesTools(BaseTool): async def get_resource_events( self, - resource_id: str = Field( + resource_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the resource. Use `prowler_list_resources` to find the right ID, or get it from a finding's resource relationship via `prowler_get_finding_details`." ), lookback_days: int = Field( diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/roles.py b/mcp_server/prowler_mcp_server/prowler_app/tools/roles.py index 113694d8e8..8fc4daa20b 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/roles.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/roles.py @@ -11,8 +11,11 @@ adding to it. from typing import Any +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.errors import ProwlerAPIError +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.roles import ( DetailedRole, RolesListResponse, @@ -70,7 +73,7 @@ class RolesTools(BaseTool): async def get_role( self, - role_id: str = Field( + role_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the role to retrieve. Use `prowler_list_roles` to find role IDs if you only know a name." ), ) -> dict[str, Any]: @@ -98,7 +101,7 @@ class RolesTools(BaseTool): async def get_user_roles( self, - user_id: str = Field( + user_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the user whose roles you want. Use `prowler_list_users` to find user IDs, or `prowler_get_current_user` for the caller." ), ) -> dict[str, Any]: @@ -124,10 +127,10 @@ class RolesTools(BaseTool): async def set_user_role( self, - user_id: str = Field( + user_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the user whose role you want to set. Use `prowler_list_users` to find user IDs." ), - role_id: str = Field( + role_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the role the user should hold. Use `prowler_list_roles` to find role IDs." ), ) -> dict[str, Any]: @@ -166,11 +169,20 @@ class RolesTools(BaseTool): # user with no role at all. Confirm the role exists before replacing. try: await self.api_client.get(f"/roles/{role_id}") - except Exception as e: - raise ValueError( - f"Role {role_id} could not be read ({e}), so user {user_id} was left " - f"unchanged. Use `prowler_list_roles` to find a valid role ID." - ) from e + except ProwlerAPIError as e: + if e.status_code != 404: + # Only a not-found says anything about the role ID. A permission + # error, a rate limit or a server error is about the request, so + # it goes to the shared classifier rather than being reported as + # an ID the caller should replace. + raise + # No `from` clause: this says what state the user was left in, which + # the shared classifier cannot know, and a cause would let it replace + # this message with its own. + raise ToolError( + f"Role {role_id} does not exist in this tenant, so user {user_id} was " + f"left unchanged. Use `prowler_list_roles` to find a valid role ID." + ) # PATCH replaces the user's whole role set with this single role, the # same call the Prowler UI makes when changing a user's role. diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/scans.py b/mcp_server/prowler_mcp_server/prowler_app/tools/scans.py index 21d1431b71..106fe69d0d 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/scans.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/scans.py @@ -5,8 +5,10 @@ This module provides tools for managing and monitoring Prowler security scans. from typing import Any, Literal +from fastmcp.exceptions import ToolError from pydantic import Field +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.scans import ( DetailedScan, ScanCreationResult, @@ -127,7 +129,7 @@ class ScansTools(BaseTool): async def get_scan( self, - scan_id: str = Field( + scan_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the scan to retrieve, generated when the scan was created (e.g., '123e4567-e89b-12d3-a456-426614174000'). Use `prowler_list_scans` tool to find scan IDs" ), ) -> dict[str, Any]: @@ -171,10 +173,10 @@ class ScansTools(BaseTool): async def trigger_scan( self, - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the provider to scan, generated when the provider was registered in the system (e.g., '4d0e2614-6385-4fa7-bf0b-c2e2f75c6877'). Use `prowler_search_providers` tool to find the provider ID" ), - name: str | None = Field( + name: NonBlankStr | None = Field( default=None, description="Optional human-friendly name for the scan. Use descriptive names to identify scan purpose or context, e.g., 'Weekly Production Security Audit', 'Pre-Deployment Validation', 'Compliance Check Q4 2025'", ), @@ -191,60 +193,70 @@ class ScansTools(BaseTool): 3. Use `prowler_get_scan` with the returned scan 'id' to monitor progress 4. Once completed, use `prowler_search_security_findings` to analyze results """ - try: - # Build request data - request_data: dict[str, Any] = { - "data": { - "type": "scans", - "attributes": {}, - "relationships": { - "provider": { - "data": { - "type": "providers", - "id": provider_id, - }, + # Build request data + request_data: dict[str, Any] = { + "data": { + "type": "scans", + "attributes": {}, + "relationships": { + "provider": { + "data": { + "type": "providers", + "id": provider_id, }, }, }, - } - if name: - request_data["data"]["attributes"]["name"] = name + }, + } + if name: + request_data["data"]["attributes"]["name"] = name - # Create scan (returns Task) - self.logger.info(f"Creating scan for provider {provider_id}") - task_response = await self.api_client.post("/scans", json_data=request_data) + # Create scan (returns Task) + self.logger.info(f"Creating scan for provider {provider_id}") + task_response = await self.api_client.post("/scans", json_data=request_data) - scan_id = ( - task_response.get("data", {}) - .get("attributes", {}) - .get("task_args", {}) - .get("scan_id", None) + scan_id = ( + task_response.get("data", {}) + .get("attributes", {}) + .get("task_args", {}) + .get("scan_id", None) + ) + + if not scan_id: + # The scan may well have been queued, so this must not read as + # "nothing happened" and invite a duplicate run. No `from` clause: + # this names the provider and the tool that checks for the scan, + # neither of which the shared classifier can know. + raise ToolError( + "Prowler accepted the scan but did not return its ID, so it " + "cannot be looked up. Use prowler_list_scans for provider " + f"{provider_id} to see whether a scan is already running before " + "triggering another one." ) - if not scan_id: - raise Exception("No scan_id returned from scan creation") - - self.logger.info(f"Scan created successfully: {scan_id}") + # The scan exists from here on, so a failure to read it back must name + # the ID rather than read as "the scan was not created". + try: scan_response = await self.api_client.get(f"/scans/{scan_id}") scan_info = DetailedScan.from_api_response(scan_response["data"]) - - return ScanCreationResult( - scan=scan_info, - status="success", - message=f"Scan {scan_id} created successfully. The scan may take some time to complete. Use prowler_get_scan tool with this ID to monitor progress.", - ).model_dump() - except Exception as e: - self.logger.error(f"Scan creation failed: {e}") - return ScanCreationResult( - scan=None, - status="failed", - message=f"Scan creation failed: {str(e)}", - ).model_dump() + # The failure itself is logged, not relayed: what it says is the + # shared classifier's to mask, and what the caller needs is the ID. + self.logger.error(f"Scan {scan_id} could not be read back: {e}") + raise ToolError( + f"Scan {scan_id} was created for provider {provider_id}, but reading " + "its state failed. Use prowler_get_scan with that ID to monitor " + "it. Do not trigger the scan again." + ) + + return ScanCreationResult( + scan=scan_info, + message=f"Scan {scan_id} created successfully. The scan may take some time to complete. Use prowler_get_scan tool with this ID to monitor progress.", + ).model_dump() async def schedule_daily_scan( self, - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the provider to scan, generated when the provider was registered in the system (e.g., '4d0e2614-6385-4fa7-bf0b-c2e2f75c6877'). Use `prowler_search_providers` tool to find the provider ID" ), ) -> dict[str, Any]: @@ -280,26 +292,49 @@ class ScansTools(BaseTool): }, }, ) - task_state = ( + + # Reaching this line means the schedule exists. Prowler commits the + # recurring schedule and its first scan inside the transaction that + # serves this request, so an answer at all means it was created; a + # provider that already has one is refused with a 409 instead, which + # leaves this tool as an error. + # + # The task in the answer is the FIRST scan run, queued to start a few + # seconds later, not the schedule. Its state therefore says nothing + # about whether the schedule was created, and reporting it as the + # outcome would call a schedule that exists a failure and invite a + # retry that can only hit that 409. + first_run_state = ( task_response.get("data", {}).get("attributes", {}).get("state", None) ) - if task_state == "available": - return_message = "Daily schedule created successfully. The schedule is being set up in the background. Use prowler_list_scans with provider_id filter to view scheduled scans." - else: - return_message = "Daily schedule creation failed. Please try again later." + message = ( + f"Daily schedule created for provider {provider_id}. Prowler will scan it " + "every 24 hours until the provider is deleted. Use prowler_list_scans with " + "this provider_id and trigger='scheduled' to view its scheduled scans." + ) + + if first_run_state in ("failed", "cancelled"): + # Worth saying: the schedule stands, but the run that was supposed to + # start now will not produce findings, and only a manual scan fills + # the gap before tomorrow. + message = ( + f"{message} Note that the first scan, which Prowler starts immediately, " + f"ended as '{first_run_state}'. The daily schedule is unaffected, but " + "use prowler_trigger_scan if you need results before the next run." + ) return ScheduleCreationResult( - scheduled=(task_state == "available"), - message=return_message, + first_run_state=first_run_state, + message=message, ).model_dump() async def update_scan( self, - scan_id: str = Field( + scan_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the scan to update, generated when the scan was created (e.g., '123e4567-e89b-12d3-a456-426614174000'). Use `prowler_list_scans` tool to find the scan ID if you only know the provider or scan name. Returns an error if the scan ID is invalid or not found." ), - name: str = Field( + name: NonBlankStr = Field( description="New human-friendly name for the scan (3-100 characters). Use descriptive names to improve organization and tracking, e.g., 'Production Security Audit - Q4 2025', 'Post-Deployment Compliance Check'. IMPORTANT: Only the scan name can be updated - other attributes (state, progress, duration) are read-only and managed by the system." ), ) -> dict[str, Any]: diff --git a/mcp_server/prowler_mcp_server/prowler_app/tools/users.py b/mcp_server/prowler_mcp_server/prowler_app/tools/users.py index a7e31b60ad..f9b71ccd84 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/tools/users.py +++ b/mcp_server/prowler_mcp_server/prowler_app/tools/users.py @@ -9,6 +9,7 @@ from typing import Any from pydantic import Field +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_app.models.users import ( DetailedUser, UsersListResponse, @@ -79,7 +80,7 @@ class UsersTools(BaseTool): async def get_user( self, - user_id: str = Field( + user_id: NonBlankStr = Field( description="Prowler's internal UUID (v4) for the user to retrieve. Use `prowler_list_users` to find user IDs if you only know a name or email." ), ) -> dict[str, Any]: diff --git a/mcp_server/prowler_mcp_server/prowler_app/utils/api_client.py b/mcp_server/prowler_mcp_server/prowler_app/utils/api_client.py index 217496a347..cb4fbd87e8 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/utils/api_client.py +++ b/mcp_server/prowler_mcp_server/prowler_app/utils/api_client.py @@ -118,7 +118,21 @@ class ProwlerAPIClient(metaclass=SingletonMeta): if detail: message = f"{message} - {detail}" - raise ProwlerAPIError(message, status, detail=detail) from e + # Carried on the exception, not into the message: a tool needs the + # body to tell an answer with an error status -- a 404 holding the + # empty result of a query that matched nothing -- apart from a + # request that actually failed. + try: + body = e.response.json() + except ValueError: + body = None + + raise ProwlerAPIError( + message, + status, + detail=detail, + payload=body if isinstance(body, dict) else None, + ) from e except httpx.RequestError as e: # No answer came back, so whether the request was applied is unknown. logger.error(f"Error during {method.value} {path}: {e}") diff --git a/mcp_server/prowler_mcp_server/prowler_app/utils/auth.py b/mcp_server/prowler_mcp_server/prowler_app/utils/auth.py index eff5d3a117..1af63920ec 100644 --- a/mcp_server/prowler_mcp_server/prowler_app/utils/auth.py +++ b/mcp_server/prowler_mcp_server/prowler_app/utils/auth.py @@ -6,6 +6,7 @@ from datetime import datetime from fastmcp.server.dependencies import get_http_headers from prowler_mcp_server import __version__ +from prowler_mcp_server.lib.errors import CredentialError from prowler_mcp_server.lib.logger import logger @@ -64,7 +65,12 @@ class ProwlerAppAuth: # Decode and parse JSON decoded = base64.b64decode(base64_payload).decode("utf-8") - return json.loads(decoded) + payload = json.loads(decoded) + + # A JWT payload is a JSON object. A list or a scalar decodes just as + # cleanly, so the type is checked here rather than left to blow up as + # an AttributeError on the first claim read. + return payload if isinstance(payload, dict) else None except Exception as e: logger.warning(f"Failed to parse JWT token: {e}") return None @@ -76,14 +82,16 @@ class ProwlerAppAuth: authorization_header = headers.get("authorization", None) if not authorization_header: - raise ValueError("No authorization header provided") + raise CredentialError("No Authorization header was sent") - # Extract token from Bearer header - if authorization_header.startswith("Bearer "): - token = authorization_header.replace("Bearer ", "") - else: - raise ValueError( - "Invalid authorization header format. Expected 'Bearer '" + # Extract token from Bearer header. Authentication scheme names are + # case-insensitive (RFC 7235), and only the scheme prefix is removed: + # a token that happens to contain the word again keeps it. + scheme, _, credential = authorization_header.partition(" ") + token = credential.strip() + if scheme.lower() != "bearer" or not token: + raise CredentialError( + "The Authorization header is not in 'Bearer ' form" ) # Check if it's an API key or JWT token @@ -94,17 +102,29 @@ class ProwlerAppAuth: # JWT token - validate and check expiration payload = self._parse_jwt(token) if not payload: - raise ValueError("Invalid JWT token format") + raise CredentialError("The token is not a readable JWT") + + # Check if token is expired. `exp` is a numeric date in the + # spec, so a missing or non-numeric one makes the token + # unusable rather than merely stale -- comparing it would raise + # a TypeError and leave the failure masked as unclassified. + exp = payload.get("exp") + if isinstance(exp, bool) or not isinstance(exp, (int, float)): + raise CredentialError( + "The token carries no readable 'exp' expiration claim" + ) - # Check if token is expired now = int(datetime.now().timestamp()) - exp = payload.get("exp", 0) if exp <= now: - raise ValueError("Token has expired") + raise CredentialError("The token has expired") return token else: - raise ValueError(f"Invalid mode: {self.mode}") + # PROWLER_MCP_TRANSPORT_MODE holds something this server does not + # support. Nothing about a call caused it and nothing about a call + # can fix it, so it stays unclassified: masked for the model, logged + # for whoever runs the server. + raise RuntimeError(f"Invalid mode: {self.mode}") async def get_valid_token(self) -> str: """Get a valid token (API key or JWT token).""" diff --git a/mcp_server/prowler_mcp_server/prowler_documentation/server.py b/mcp_server/prowler_mcp_server/prowler_documentation/server.py index 9588302168..de0756a505 100644 --- a/mcp_server/prowler_mcp_server/prowler_documentation/server.py +++ b/mcp_server/prowler_mcp_server/prowler_documentation/server.py @@ -3,6 +3,7 @@ from typing import Any from fastmcp import FastMCP from pydantic import Field +from prowler_mcp_server.lib.types import NonBlankStr from prowler_mcp_server.prowler_documentation.search_engine import ( ProwlerDocsSearchEngine, ) @@ -14,7 +15,9 @@ prowler_docs_search_engine = ProwlerDocsSearchEngine() @docs_mcp_server.tool() def search( - term: str = Field(description="The term to search for in the documentation"), + term: NonBlankStr = Field( + description="The term to search for in the documentation" + ), page_size: int = Field( 5, description="Number of top results to return. It must be between 1 and 20.", @@ -39,7 +42,7 @@ def search( @docs_mcp_server.tool() def get_document( - doc_path: str = Field( + doc_path: NonBlankStr = Field( description="Path to the documentation file to retrieve. It is the same as the 'path' field of the search results. Use `prowler_docs_search` to find the path first." ), ) -> dict[str, str]: diff --git a/mcp_server/prowler_mcp_server/prowler_hub/server.py b/mcp_server/prowler_mcp_server/prowler_hub/server.py index 41e83eca90..8d18a2c240 100644 --- a/mcp_server/prowler_mcp_server/prowler_hub/server.py +++ b/mcp_server/prowler_mcp_server/prowler_hub/server.py @@ -9,6 +9,7 @@ from fastmcp import FastMCP from pydantic import Field from prowler_mcp_server import __version__ +from prowler_mcp_server.lib.types import NonBlankStr # Initialize FastMCP for Prowler Hub hub_mcp_server = FastMCP("prowler-hub") @@ -149,7 +150,7 @@ async def list_checks( @hub_mcp_server.tool() async def semantic_search_checks( - term: str = Field( + term: NonBlankStr = Field( description="Search term. Examples: 'public access', 'encryption', 'MFA', 'logging'.", ), ) -> dict: @@ -208,7 +209,7 @@ async def semantic_search_checks( @hub_mcp_server.tool() async def get_check_details( - check_id: str = Field( + check_id: NonBlankStr = Field( description="The check ID to retrieve details for. Example: 's3_bucket_level_public_access_block'" ), ) -> dict: @@ -346,10 +347,10 @@ async def get_check_details( @hub_mcp_server.tool() async def get_check_code( - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="Prowler Provider ID. Example: 'aws', 'azure', 'gcp', 'kubernetes'. Use `prowler_hub_list_providers` to get available provider IDs.", ), - check_id: str = Field( + check_id: NonBlankStr = Field( description="The check ID. Example: 's3_bucket_public_access'. Get IDs from `prowler_hub_list_checks` or `prowler_hub_search_checks`.", ), ) -> dict: @@ -392,10 +393,10 @@ async def get_check_code( @hub_mcp_server.tool() async def get_check_fixer( - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="Prowler Provider ID. Example: 'aws', 'azure', 'gcp', 'kubernetes'. Use `prowler_hub_list_providers` to get available provider IDs.", ), - check_id: str = Field( + check_id: NonBlankStr = Field( description="The check ID. Example: 's3_bucket_public_access'. Get IDs from `prowler_hub_list_checks` or `prowler_hub_search_checks`.", ), ) -> dict: @@ -517,7 +518,7 @@ async def list_compliances( @hub_mcp_server.tool() async def semantic_search_compliances( - term: str = Field( + term: NonBlankStr = Field( description="Search term. Examples: 'CIS', 'HIPAA', 'PCI', 'GDPR', 'SOC2', 'NIST'.", ), ) -> dict: @@ -568,7 +569,7 @@ async def semantic_search_compliances( @hub_mcp_server.tool() async def get_compliance_details( - compliance_id: str = Field( + compliance_id: NonBlankStr = Field( description="The compliance framework ID to retrieve details for. Example: 'cis_4.0_aws'. Use `prowler_hub_list_compliances` or `prowler_hub_semantic_search_compliances` to find available compliance IDs.", ), ) -> dict: @@ -708,7 +709,7 @@ async def list_providers() -> dict: @hub_mcp_server.tool() async def get_provider_services( - provider_id: str = Field( + provider_id: NonBlankStr = Field( description="The provider ID to get services for. Example: 'aws', 'azure', 'gcp', 'kubernetes'. Use `prowler_hub_list_providers` to get available provider IDs.", ), ) -> dict: diff --git a/mcp_server/tests/lib/test_errors.py b/mcp_server/tests/lib/test_errors.py index 5986d883c4..cd32752b42 100644 --- a/mcp_server/tests/lib/test_errors.py +++ b/mcp_server/tests/lib/test_errors.py @@ -11,7 +11,11 @@ import pytest from fastmcp import Client from pydantic import BaseModel, ValidationError -from prowler_mcp_server.lib.errors import InvalidArgument, _describe_failure +from prowler_mcp_server.lib.errors import ( + CredentialError, + InvalidArgument, + _describe_failure, +) from prowler_mcp_server.prowler_app.utils.api_client import ( ProwlerAPIError, ProwlerAPIInvalidResponse, @@ -99,6 +103,19 @@ def test_an_argument_this_server_rejected_is_repeated_verbatim(): assert message == "page_size must be between 1 and 1000." +def test_a_credential_caught_here_is_answered_like_the_401_it_would_have_got(): + """It is not an argument problem, and saying so stops a pointless retry.""" + message = _describe_failure(CredentialError("the token has expired")) + + assert "the token has expired" in message + assert "changing the arguments will not help" in message + + +def test_a_transport_this_server_cannot_serve_is_left_masked(): + """No call caused a bad PROWLER_MCP_TRANSPORT_MODE and no call can fix it.""" + assert _describe_failure(RuntimeError("Invalid mode: websocket")) is None + + def test_a_pydantic_rejection_names_the_field_without_echoing_the_value(): """Pydantic quotes `input_value` back, and these tools take credentials.""" @@ -195,3 +212,18 @@ async def test_an_unreadable_api_answer_does_not_reach_the_agent_as_a_bad_argume assert result.isError is True assert "gateway timeout" not in result.content[0].text assert "argument" not in result.content[0].text + + +async def test_a_tool_specific_message_survives_masking( + mcp_root_server, mock_api_client, mock_router +): + """A `ToolError` raised without a `from` clause is the final word.""" + mock_router.add("GET", "/api/v1/integrations/i1", json={"data": None}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_get_integration", {"integration_id": "i1"} + ) + + assert result.isError is True + assert "prowler_list_integrations" in result.content[0].text diff --git a/mcp_server/tests/lib/test_types.py b/mcp_server/tests/lib/test_types.py new file mode 100644 index 0000000000..8af25a7aae --- /dev/null +++ b/mcp_server/tests/lib/test_types.py @@ -0,0 +1,125 @@ +"""Tests for the argument types every tool shares. + +The bug these pin: "required" alone does not stop a blank identifier. A model +that has no scan or query id to hand sends ``""`` rather than omitting the +argument, and an unguarded empty string travels into a URL path or a request +body -- where it comes back as a 404, or as an API rejection ("This field may +not be blank") that names no argument and leaves the model with nothing to fix. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.jsonapi import jsonapi_collection, jsonapi_resource + +SCAN_ID = "019ac0d6-90d5-73e9-9acf-c22e256f1bac" +QUERIES = f"/api/v1/attack-paths-scans/{SCAN_ID}/queries" + + +@pytest.mark.parametrize("query_id", ["", " "], ids=["empty", "whitespace-only"]) +async def test_a_blank_identifier_is_rejected_before_any_request_goes_out( + mcp_root_server, mock_api_client, mock_router, query_id +): + """The reported failure: a blank `query_id` reached Prowler as a 400. + + The message has to name the argument. Prowler's own answer to the blank value + ("This field may not be blank") does not say which field, so the model had no + way to tell `scan_id` from `query_id` from the reply. + """ + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_run_attack_paths_query", + {"scan_id": SCAN_ID, "query_id": query_id}, + ) + + assert result.isError is True + assert "query_id" in result.content[0].text + assert mock_router.requests == [] + + +async def test_an_identifier_keeps_its_surrounding_whitespace_out_of_the_url( + mcp_root_server, mock_api_client, mock_router +): + """A padded id is the same id, and a raw one would build a URL-escaped path.""" + mock_router.add("GET", QUERIES, json=jsonapi_collection([])) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_list_attack_paths_queries", {"scan_id": f" {SCAN_ID} "} + ) + + assert result.isError is False + assert mock_router.paths() == [f"GET {QUERIES}"] + + +async def test_a_blank_optional_value_is_rejected_rather_than_written( + mcp_root_server, mock_api_client, mock_router +): + """An omitted optional means "leave it alone"; a blank one would blank the field. + + The API refuses it, so the only difference an unguarded blank makes is a + round trip and an error that names nothing. + """ + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_update_mute_rule", {"rule_id": SCAN_ID, "name": ""} + ) + + assert result.isError is True + assert "name" in result.content[0].text + assert mock_router.requests == [] + + +async def test_an_omitted_optional_string_is_still_omitted( + mcp_root_server, mock_api_client, mock_router +): + """`NonBlankStr | None` must not turn "not provided" into a rejection.""" + mock_router.add( + "GET", + f"/api/v1/mute-rules/{SCAN_ID}", + json={ + "data": jsonapi_resource( + "mute-rules", + SCAN_ID, + { + "name": "unchanged", + "reason": "already reviewed", + "enabled": True, + "finding_uids": [], + }, + ) + }, + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_update_mute_rule", {"rule_id": SCAN_ID} + ) + + assert result.isError is False + + +async def test_every_required_string_argument_is_guarded_against_a_blank( + mcp_root_server, +): + """A guard only one tool carries is one the next tool will be written without. + + Declared as `minLength` rather than checked inside each tool, so a client sees + the constraint in the schema before it calls. + """ + async with Client(mcp_root_server) as client: + tools = await client.list_tools() + + unguarded = [ + f"{tool.name}.{name}" + for tool in tools + for name, schema in tool.inputSchema.get("properties", {}).items() + # Plain required strings only. A union such as `dict | str` takes a JSON + # string, where a blank is a parse failure the classifier already + # explains, and a blank filter is a filter that matches everything. + if schema.get("type") == "string" + and name in tool.inputSchema.get("required", []) + and schema.get("minLength") != 1 + ] + + assert unguarded == [] diff --git a/mcp_server/tests/prowler_app/tools/test_attack_paths.py b/mcp_server/tests/prowler_app/tools/test_attack_paths.py new file mode 100644 index 0000000000..3f20549796 --- /dev/null +++ b/mcp_server/tests/prowler_app/tools/test_attack_paths.py @@ -0,0 +1,225 @@ +"""Tests for the Attack Paths tools. + +An Attack Paths scan is a separate resource from a regular scan, with IDs of its +own, and Prowler only creates one for an AWS provider. So the 404 these tools get +is almost always a regular scan ID passed where an Attack Paths one belongs -- +and Prowler's own reason for it, a bare "Not found.", names neither the resource +it looked in nor the tool that returns the right ID. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.jsonapi import jsonapi_collection, jsonapi_resource + +QUERIES = "/api/v1/attack-paths-scans/s1/queries" + + +async def test_an_id_that_is_not_an_attack_paths_scan_says_which_tool_returns_one( + mcp_root_server, mock_api_client, mock_router +): + """Relaying "Not found." sends an agent to re-check an ID it cannot fix. + + The reply has to name the confusion it stands for: regular scan IDs do not + resolve here, and only AWS providers have an Attack Paths scan at all. + """ + mock_router.add( + "GET", + QUERIES, + status=404, + json={"errors": [{"status": "404", "detail": "Not found."}]}, + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="different resource from regular scans"): + await client.call_tool( + "prowler_list_attack_paths_queries", {"scan_id": "s1"} + ) + + +async def test_the_answer_names_the_tool_that_returns_a_usable_id( + mcp_root_server, mock_api_client, mock_router +): + """An explanation with no next step leaves the agent guessing IDs.""" + mock_router.add( + "GET", + QUERIES, + status=404, + json={"errors": [{"status": "404", "detail": "Not found."}]}, + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="prowler_list_attack_paths_scans"): + await client.call_tool( + "prowler_list_attack_paths_queries", {"scan_id": "s1"} + ) + + +async def test_a_failure_that_is_not_a_404_keeps_the_shared_message( + mcp_root_server, mock_api_client, mock_router +): + """Only the 404 means a bad ID. A 403 is a permission the ID cannot fix.""" + mock_router.add( + "GET", + QUERIES, + status=403, + json={"errors": [{"status": "403", "detail": "Denied."}]}, + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="prowler_get_current_user"): + await client.call_tool( + "prowler_list_attack_paths_queries", {"scan_id": "s1"} + ) + + +async def test_queries_come_back_as_a_list( + mcp_root_server, mock_api_client, mock_router +): + """The success path is unchanged.""" + mock_router.add( + "GET", + QUERIES, + json=jsonapi_collection( + [ + jsonapi_resource( + "attack-paths-queries", + "aws-ec2-instances-internet-exposed", + { + "name": "Internet exposed EC2", + "description": "Find internet-exposed EC2 instances", + "provider": "aws", + "parameters": [], + }, + ) + ] + ), + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_list_attack_paths_queries", {"scan_id": "s1"} + ) + + assert result.data[0]["id"] == "aws-ec2-instances-internet-exposed" + + +# ------------------------------------------------------------- running a query + +RUN = "/api/v1/attack-paths-scans/s1/queries/run" +SCHEMA = "/api/v1/attack-paths-scans/s1/schema" + +EMPTY_RESULT = { + "data": { + "type": "attack-paths-query-results", + "id": "s1", + "attributes": {"nodes": [], "relationships": []}, + } +} + + +def _run_args(query_id: str = "aws-ec2-instances-internet-exposed") -> dict[str, str]: + """Arguments for a query run against the mocked scan.""" + return {"scan_id": "s1", "query_id": query_id} + + +async def test_a_query_that_matched_nothing_is_an_answer_not_a_failure( + mcp_root_server, mock_api_client, mock_router +): + """Prowler answers a query that matched nothing with 404 and the result body. + + Raising on the status called a clean account a failed call and sent the agent + off to re-check arguments that were right. + """ + mock_router.add("POST", RUN, status=404, json=EMPTY_RESULT) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_run_attack_paths_query", _run_args() + ) + + assert result.isError is False + assert "matched nothing" in result.structuredContent["message"] + + +async def test_an_empty_result_does_not_come_back_as_an_empty_object( + mcp_root_server, mock_api_client, mock_router +): + """The serializer drops empty lists, so `{}` is all that would be left.""" + mock_router.add("POST", RUN, status=404, json=EMPTY_RESULT) + + async with Client(mcp_root_server) as client: + result = await client.call_tool("prowler_run_attack_paths_query", _run_args()) + + assert result.data != {} + + +async def test_a_null_graph_is_read_as_an_empty_one( + mcp_root_server, mock_api_client, mock_router +): + """Prowler can spell the empty graph as `null` rather than as empty lists. + + Reading `null` as if it were a graph crashed the parse, turning the same + "nothing matched" answer into an error the agent could not act on. + """ + mock_router.add("POST", RUN, status=404, json={"data": {"attributes": None}}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_run_attack_paths_query", _run_args() + ) + + assert result.isError is False + assert "matched nothing" in result.structuredContent["message"] + + +async def test_a_run_against_an_unknown_scan_still_names_the_confusion( + mcp_root_server, mock_api_client, mock_router +): + """A 404 with no result body is the ID being wrong, not an empty answer.""" + mock_router.add( + "POST", + RUN, + status=404, + json={"errors": [{"status": "404", "detail": "Not found."}]}, + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="different resource from regular scans"): + await client.call_tool("prowler_run_attack_paths_query", _run_args()) + + +async def test_a_scan_whose_graph_records_no_schema_says_so( + mcp_root_server, mock_api_client, mock_router +): + """This 404 is about the graph, not the ID, so it must not blame the ID.""" + mock_router.add( + "GET", + SCHEMA, + status=404, + json={"detail": "No cartography schema metadata found for this provider"}, + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="no Cartography schema recorded"): + await client.call_tool( + "prowler_get_attack_paths_cartography_schema", {"scan_id": "s1"} + ) + + +async def test_a_schema_request_for_an_unknown_scan_names_the_confusion( + mcp_root_server, mock_api_client, mock_router +): + """The other 404 here is the ID, and Prowler writes a JSON:API error for it.""" + mock_router.add( + "GET", + SCHEMA, + status=404, + json={"errors": [{"status": "404", "detail": "Not found."}]}, + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="different resource from regular scans"): + await client.call_tool( + "prowler_get_attack_paths_cartography_schema", {"scan_id": "s1"} + ) diff --git a/mcp_server/tests/prowler_app/tools/test_compliance.py b/mcp_server/tests/prowler_app/tools/test_compliance.py new file mode 100644 index 0000000000..373e1d7f6c --- /dev/null +++ b/mcp_server/tests/prowler_app/tools/test_compliance.py @@ -0,0 +1,102 @@ +"""Tests for the compliance tools. + +Both compliance tools answer for exactly one scan. ``scan_id`` names it +directly; ``provider_id`` names it indirectly, as "the latest completed scan of +this provider". Passing both is not a refinement of either -- the scan the +caller named may belong to a different provider entirely -- so it is rejected +rather than resolved by preferring one, which would answer confidently for a +provider nobody asked about. + +Tools are driven through an in-memory MCP client so FastMCP resolves the +pydantic ``Field`` defaults and a raised failure arrives the way a client sees +it. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.jsonapi import jsonapi_collection, jsonapi_resource + +SCANS = "/api/v1/scans" +OVERVIEWS = "/api/v1/compliance-overviews" +REQUIREMENTS = f"{OVERVIEWS}/requirements" + +TOOLS = [ + "prowler_get_compliance_overview", + "prowler_get_compliance_framework_state_details", +] + + +def arguments(tool: str, **overrides) -> dict: + """Build the arguments for either tool, which differ only in compliance_id.""" + payload = dict(overrides) + if tool.endswith("framework_state_details"): + payload["compliance_id"] = "cis_1.5_aws" + return payload + + +@pytest.mark.parametrize("tool", TOOLS) +async def test_neither_a_scan_nor_a_provider_is_refused_before_any_request( + mcp_root_server, mock_api_client, mock_router, tool +): + """There is no scan to answer for, and no way to guess one.""" + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="must be provided"): + await client.call_tool(tool, arguments(tool)) + + assert mock_router.paths() == [] + + +@pytest.mark.parametrize("tool", TOOLS) +async def test_a_scan_and_a_provider_together_are_refused_rather_than_reconciled( + mcp_root_server, mock_api_client, mock_router, tool +): + """Silently keeping the scan would answer for whichever provider owns it. + + That report names a scan the caller did ask for, so nothing about it looks + wrong -- while the provider they also named went unread. + """ + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="not both"): + await client.call_tool( + tool, arguments(tool, scan_id="s1", provider_id="p1") + ) + + assert mock_router.paths() == [] + + +@pytest.mark.parametrize("tool", TOOLS) +async def test_a_provider_on_its_own_resolves_to_its_latest_completed_scan( + mcp_root_server, mock_api_client, mock_router, tool +): + """The indirection is the point of accepting a provider at all.""" + mock_router.add( + "GET", + SCANS, + json=jsonapi_collection( + [jsonapi_resource("scans", "s9", {"state": "completed"})] + ), + ) + mock_router.add("GET", OVERVIEWS, json=jsonapi_collection([])) + mock_router.add("GET", REQUIREMENTS, json=jsonapi_collection([])) + # Each tool reads the compliance state from its own endpoint; both filter it + # by the scan that had to be resolved first. + read = OVERVIEWS if tool.endswith("overview") else REQUIREMENTS + + async with Client(mcp_root_server) as client: + await client.call_tool(tool, arguments(tool, provider_id="p1")) + + assert mock_router.query_params("GET", SCANS)["filter[provider]"] == "p1" + assert mock_router.query_params("GET", read)["filter[scan_id]"] == "s9" + + +@pytest.mark.parametrize("tool", TOOLS) +async def test_a_provider_with_no_completed_scan_is_named_as_the_bad_argument( + mcp_root_server, mock_api_client, mock_router, tool +): + """Nothing has been scanned yet, so there is no compliance state to report.""" + mock_router.add("GET", SCANS, json=jsonapi_collection([])) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="No completed scans found for provider p1"): + await client.call_tool(tool, arguments(tool, provider_id="p1")) diff --git a/mcp_server/tests/prowler_app/tools/test_integrations.py b/mcp_server/tests/prowler_app/tools/test_integrations.py index 9d165a60c6..d94dd8a21d 100644 --- a/mcp_server/tests/prowler_app/tools/test_integrations.py +++ b/mcp_server/tests/prowler_app/tools/test_integrations.py @@ -312,17 +312,16 @@ async def test_creating_a_jira_integration_rejects_an_empty_domain( ): """A domain that normalizes to nothing is caught before the round trip.""" async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_create_jira_integration", - { - "domain": "https://", - "user_mail": "security@acme.com", - "api_token": "fake-atlassian-token-for-testing", - }, - ) + with pytest.raises(Exception, match="Invalid Jira domain"): + await client.call_tool( + "prowler_create_jira_integration", + { + "domain": "https://", + "user_mail": "security@acme.com", + "api_token": "fake-atlassian-token-for-testing", + }, + ) - assert result.data["status"] == "failed" - assert "Invalid Jira domain" in result.data["error"] assert mock_router.requests == [] @@ -334,14 +333,10 @@ async def test_creating_a_jira_integration_rejects_an_empty_domain( ], ids=["security-hub", "amazon-s3"], ) -async def test_a_rejected_creation_is_reported_rather_than_raised( +async def test_a_rejected_creation_fails_with_the_api_reason( mcp_root_server, mock_api_client, mock_router, tool, arguments ): - """Write tools answer with an error object so the agent can act on it. - - A raised exception reaches the model as a tool failure with no detail, and - the API's message is exactly what tells it what to do next. - """ + """A refused creation is a tool error, and it still carries the API's reason.""" mock_router.add( "POST", INTEGRATIONS, @@ -350,10 +345,8 @@ async def test_a_rejected_creation_is_reported_rather_than_raised( ) async with Client(mcp_root_server) as client: - result = await client.call_tool(tool, arguments) - - assert result.data["status"] == "failed" - assert "already has this integration" in result.data["error"] + with pytest.raises(Exception, match="already has this integration"): + await client.call_tool(tool, arguments) async def test_a_creation_with_no_id_back_warns_before_a_blind_retry( @@ -367,12 +360,11 @@ async def test_a_creation_with_no_id_back_warns_before_a_blind_retry( mock_router.add("POST", INTEGRATIONS, json={"data": {}}) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_create_amazon_s3_integration", {"bucket_name": "my-reports"} - ) + with pytest.raises(Exception, match="did not return its ID"): + await client.call_tool( + "prowler_create_amazon_s3_integration", {"bucket_name": "my-reports"} + ) - assert result.data["status"] == "failed" - assert "did not return its ID" in result.data["error"] assert mock_router.paths() == [f"POST {INTEGRATIONS}"] @@ -395,12 +387,10 @@ async def test_a_creation_whose_read_back_fails_still_hands_over_the_id( ) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_create_amazon_s3_integration", {"bucket_name": "my-reports"} - ) - - assert result.data["status"] == "failed" - assert "Integration i1 was created" in result.data["error"] + with pytest.raises(Exception, match="Integration i1 was created"): + await client.call_tool( + "prowler_create_amazon_s3_integration", {"bucket_name": "my-reports"} + ) async def test_a_connection_check_that_cannot_run_is_not_reported_as_a_failure( @@ -542,13 +532,12 @@ async def test_a_configuration_that_is_not_an_object_is_rejected_before_the_writ stub_integration(mock_router, S3_ATTRIBUTES) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_update_integration", - {"integration_id": "i1", "configuration": configuration}, - ) + with pytest.raises(Exception, match=message): + await client.call_tool( + "prowler_update_integration", + {"integration_id": "i1", "configuration": configuration}, + ) - assert result.data["status"] == "failed" - assert message in result.data["error"] assert f"PATCH {INTEGRATION}" not in mock_router.paths() @@ -643,13 +632,12 @@ async def test_updating_a_jira_configuration_is_refused( stub_integration(mock_router, JIRA_ATTRIBUTES) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_update_integration", - {"integration_id": "i1", "configuration": {"domain": "other"}}, - ) + with pytest.raises(Exception, match="do not accept a configuration"): + await client.call_tool( + "prowler_update_integration", + {"integration_id": "i1", "configuration": {"domain": "other"}}, + ) - assert result.data["status"] == "failed" - assert "do not accept a configuration" in result.data["error"] assert f"PATCH {INTEGRATION}" not in mock_router.paths() @@ -660,12 +648,12 @@ async def test_attaching_a_jira_integration_to_a_provider_is_refused( stub_integration(mock_router, JIRA_ATTRIBUTES) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_update_integration", - {"integration_id": "i1", "provider_ids": ["p1"]}, - ) + with pytest.raises(Exception, match="tenant-wide"): + await client.call_tool( + "prowler_update_integration", + {"integration_id": "i1", "provider_ids": ["p1"]}, + ) - assert "tenant-wide" in result.data["error"] assert f"PATCH {INTEGRATION}" not in mock_router.paths() @@ -683,12 +671,12 @@ async def test_security_hub_must_keep_exactly_one_provider( stub_integration(mock_router, SECURITY_HUB_ATTRIBUTES, provider_ids=("p1",)) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_update_integration", - {"integration_id": "i1", "provider_ids": provider_ids}, - ) + with pytest.raises(Exception, match="exactly one AWS provider"): + await client.call_tool( + "prowler_update_integration", + {"integration_id": "i1", "provider_ids": provider_ids}, + ) - assert "exactly one AWS provider" in result.data["error"] assert f"PATCH {INTEGRATION}" not in mock_router.paths() @@ -708,12 +696,12 @@ async def test_partial_jira_credentials_are_refused_to_protect_the_stored_ones( stub_integration(mock_router, JIRA_ATTRIBUTES) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_update_integration", - {"integration_id": "i1", "credentials": credentials}, - ) + with pytest.raises(Exception, match="replaced as a whole"): + await client.call_tool( + "prowler_update_integration", + {"integration_id": "i1", "credentials": credentials}, + ) - assert "replaced as a whole" in result.data["error"] assert f"PATCH {INTEGRATION}" not in mock_router.paths() @@ -751,13 +739,14 @@ async def test_replacing_jira_credentials_normalizes_the_domain( # ------------------------------------------------- delete and connection tools -async def test_deleting_an_integration_reports_the_outcome_either_way( +async def test_deleting_an_integration_confirms_it_happened( mcp_root_server, mock_api_client, mock_router ): - """Deletion is irreversible, so both outcomes are stated explicitly. + """Deletion is irreversible, so a success says so rather than staying silent. - A bare exception would leave the agent unsure whether the credentials are - gone, and a retry of a delete that actually succeeded reads as a new failure. + It says so in the message and nowhere else: a `deleted: true` flag could only + ever be true, because an integration that was not deleted leaves the tool as + an error. """ mock_router.add("DELETE", INTEGRATION, status=204) @@ -766,24 +755,23 @@ async def test_deleting_an_integration_reports_the_outcome_either_way( "prowler_delete_integration", {"integration_id": "i1"} ) - assert result.data["deleted"] is True + assert "i1 deleted successfully" in result.data["message"] + assert "deleted" not in result.data -async def test_a_failed_deletion_says_it_did_not_happen( +async def test_a_refused_deletion_fails_and_says_the_role_is_the_problem( mcp_root_server, mock_api_client, mock_router ): - """`deleted: false` is the part the agent must not have to infer.""" + """A 403 is the same answer for every tool, so `lib.errors` writes it.""" mock_router.add( "DELETE", INTEGRATION, status=403, json=jsonapi_error(403, "Permission denied.") ) async with Client(mcp_root_server) as client: - result = await client.call_tool( - "prowler_delete_integration", {"integration_id": "i1"} - ) - - assert result.data["deleted"] is False - assert "Permission denied." in result.data["message"] + with pytest.raises(Exception, match="prowler_get_current_user"): + await client.call_tool( + "prowler_delete_integration", {"integration_id": "i1"} + ) async def test_checking_a_connection_surfaces_why_it_failed( @@ -1026,6 +1014,32 @@ async def test_an_accepted_dispatch_with_no_task_id_is_not_safe_to_retry( assert "task_id" not in result.data +async def test_a_dispatch_with_no_usable_credential_is_raised_not_called_unknown( + mcp_root_server, mock_api_client, mock_router, monkeypatch +): + """Authentication runs before the request, so nothing was ever queued. + + Reported as `unknown` it reads as "work items may exist in Jira, go and + look" -- for a call that never reached Prowler. It is not a dispatch outcome + at all: the credential has to be fixed, and no retry of this call does that. + """ + monkeypatch.setattr(mock_api_client.auth_manager, "mode", "http") + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="no usable credential"): + await client.call_tool( + "prowler_send_findings_to_jira", + { + "integration_id": "i1", + "project_key": "PROJ", + "issue_type": "Task", + "finding_ids": ["f1"], + }, + ) + + assert mock_router.paths() == [] + + async def test_a_dispatch_task_that_died_halfway_is_never_safe_to_retry( mcp_root_server, mock_api_client, mock_router ): diff --git a/mcp_server/tests/prowler_app/tools/test_muting.py b/mcp_server/tests/prowler_app/tools/test_muting.py new file mode 100644 index 0000000000..7c980600e3 --- /dev/null +++ b/mcp_server/tests/prowler_app/tools/test_muting.py @@ -0,0 +1,64 @@ +"""Tests for the muting tools. + +Muting is permanent and deleting a rule does not undo it, so the one thing +these assertions protect is that an agent is never told a deletion failed when +it did not: the old answer keyed off the *shape* of the API's reply rather than +off anything having gone wrong, and said nothing a caller could act on. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.jsonapi import jsonapi_document, jsonapi_error, jsonapi_resource + +MUTE_RULE = "/api/v1/mute-rules/m1" + + +async def test_a_deleted_rule_is_reported_deleted_whatever_the_body( + mcp_root_server, mock_api_client, mock_router +): + """Prowler answers 204 with no body, but 200 with one is just as much a yes. + + The old check read ``success`` out of the parsed body, which only exists for + the empty-body case, so a deletion that worked could be reported as + "Failed to delete mute rule". + """ + mock_router.add( + "DELETE", + MUTE_RULE, + json=jsonapi_document(jsonapi_resource("mute-rules", "m1", {})), + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool("prowler_delete_mute_rule", {"rule_id": "m1"}) + + assert "m1 deleted successfully" in result.data["message"] + assert "stay muted" in result.data["message"] + # A flag with one reachable value is not a fact, it is an invitation to + # branch on a shape that does not exist. + assert "success" not in result.data + + +async def test_an_empty_body_deletion_is_reported_the_same_way( + mcp_root_server, mock_api_client, mock_router +): + """The 204 path, which is what Prowler actually sends today.""" + mock_router.add("DELETE", MUTE_RULE, status=204) + + async with Client(mcp_root_server) as client: + result = await client.call_tool("prowler_delete_mute_rule", {"rule_id": "m1"}) + + assert "m1 deleted successfully" in result.data["message"] + + +async def test_a_refused_deletion_is_an_error( + mcp_root_server, mock_api_client, mock_router +): + """A rule that was not deleted has to leave the tool as an error.""" + mock_router.add( + "DELETE", MUTE_RULE, status=404, json=jsonapi_error(404, "Not found.") + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="Not found"): + await client.call_tool("prowler_delete_mute_rule", {"rule_id": "m1"}) diff --git a/mcp_server/tests/prowler_app/tools/test_providers.py b/mcp_server/tests/prowler_app/tools/test_providers.py new file mode 100644 index 0000000000..b3438a79a7 --- /dev/null +++ b/mcp_server/tests/prowler_app/tools/test_providers.py @@ -0,0 +1,316 @@ +"""Tests for the provider tools. + +Two behaviours drive most of the assertions here, and both are about telling a +failure apart from an outcome that is merely not final yet: + +* Deleting a provider removes it together with its scans, findings and + resources, in a background task that routinely outlives the polling window. + A deletion still running is not a failure, and reporting it as one invites a + retry of a destructive call that is already in flight. +* ``connect_provider`` runs a connection check, and a check that could not be + run says nothing about the provider's credentials. Reporting it as ``failed`` + blames an AWS role for an expired Prowler credential and sends the user off to + fix something that works. + +Tools are driven through an in-memory MCP client so FastMCP resolves the +pydantic ``Field`` defaults and a raised failure arrives the way a client sees +it. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.http import MockRouter +from tests.helpers.jsonapi import ( + jsonapi_collection, + jsonapi_document, + jsonapi_error, + jsonapi_resource, + task_document, +) + +PROVIDERS = "/api/v1/providers" +PROVIDER = f"{PROVIDERS}/p1" +CONNECTION = f"{PROVIDER}/connection" +SECRETS = f"{PROVIDERS}/secrets" +TASK = "/api/v1/tasks/t1" + +PROVIDER_ATTRIBUTES = { + "uid": "123456789012", + "provider": "aws", + "alias": "production", + "connection": {"connected": True}, +} + + +@pytest.fixture +def mock_fast_polling(monkeypatch, api_client): + """Run the real polling loop, with a timeout a test can afford to wait out. + + The timeout path is the one worth testing here -- it is what used to be + reported as a failed deletion -- so the loop, its exception and the fallback + that reads the task afterwards all stay real. Only the 60 seconds go. + """ + original = type(api_client).poll_task_until_complete + + async def _fast(self, task_id, **_overridden): + return await original(self, task_id, timeout=0.3, poll_interval=0.05) + + monkeypatch.setattr(type(api_client), "poll_task_until_complete", _fast) + + +@pytest.fixture +def mock_polling_timeout(monkeypatch, api_client): + """Make the polling window run out on the first call, without the wait. + + The clock is what ends the polling loop here, so a test about *what happens + afterwards* has no reason to spend it. The read the fallback then makes is + the real one. + """ + + async def _timeout(self, task_id, **_overridden): + raise TimeoutError(f"Task {task_id} polling timed out after 60 seconds.") + + monkeypatch.setattr(type(api_client), "poll_task_until_complete", _timeout) + + +def stub_deletion_start(mock_router: MockRouter) -> MockRouter: + """Serve the DELETE as Prowler does: a task to poll, not a finished deletion.""" + return mock_router.add( + "DELETE", PROVIDER, json=jsonapi_document(jsonapi_resource("tasks", "t1", {})) + ) + + +# --------------------------------------------------------------- deletion + + +async def test_a_refused_deletion_is_an_error_not_a_result( + mcp_root_server, mock_api_client, mock_router +): + """Nothing started, so the classifier owns the message. + + Returned as ``{"deleted": false}`` it arrives with ``isError: false`` and a + model has no reason to treat it as anything but a completed call. + """ + mock_router.add( + "DELETE", PROVIDER, status=403, json=jsonapi_error(403, "Not allowed.") + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="not allowed to do this"): + await client.call_tool("prowler_delete_provider", {"provider_id": "p1"}) + + +async def test_a_deletion_with_no_task_back_warns_before_a_blind_retry( + mcp_root_server, mock_api_client, mock_router +): + """Prowler accepted it, so the deletion is probably running. + + Without the task ID there is nothing to watch it with, which makes "check + whether it is gone" the only safe instruction. + """ + mock_router.add("DELETE", PROVIDER, json={"data": {}}) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="did not return the ID"): + await client.call_tool("prowler_delete_provider", {"provider_id": "p1"}) + + assert mock_router.paths() == [f"DELETE {PROVIDER}"] + + +async def test_a_finished_deletion_reports_it_plainly( + mcp_root_server, mock_api_client, mock_router +): + """The success path is unchanged: the provider is gone.""" + stub_deletion_start(mock_router) + mock_router.add("GET", TASK, json=task_document("t1", "completed")) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_delete_provider", {"provider_id": "p1"} + ) + + assert result.data["status"] == "deleted" + + +async def test_a_deletion_still_running_is_not_reported_as_a_failure( + mcp_root_server, mock_api_client, mock_router, mock_fast_polling +): + """Outliving the polling window is normal for a provider with many findings. + + The task ID goes back so the deletion can be followed, and the message says + not to send it again -- which is the whole point of not calling this failed. + """ + stub_deletion_start(mock_router) + mock_router.add("GET", TASK, json=task_document("t1", "executing")) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_delete_provider", {"provider_id": "p1"} + ) + + assert result.data["status"] == "in_progress" + assert result.data["task_id"] == "t1" + assert "Do not send the deletion again" in result.data["message"] + + +async def test_a_deletion_that_finished_just_after_the_wait_is_reported_as_deleted( + mcp_root_server, mock_api_client, mock_router, mock_polling_timeout +): + """Polling gives up on the clock, not on the task. + + A deletion that completed a moment after the last poll is a finished + deletion, and the read the fallback makes is what says so. Reporting it as + still running would send the caller off to watch a provider that is gone. + """ + stub_deletion_start(mock_router) + mock_router.add("GET", TASK, json=task_document("t1", "completed")) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_delete_provider", {"provider_id": "p1"} + ) + + assert result.data["status"] == "deleted" + assert "task_id" not in result.data + + +async def test_a_deletion_task_that_stopped_is_an_error_naming_what_is_left( + mcp_root_server, mock_api_client, mock_router +): + """Here the provider really is still there, so this one is a failure. + + A provider is removed together with everything attached to it, so a task + that stopped halfway can leave part of that gone -- which is why the message + sends the caller to look rather than asserting the state. + """ + stub_deletion_start(mock_router) + mock_router.add("GET", TASK, json=task_document("t1", "failed", error="boom")) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="ended as 'failed'"): + await client.call_tool("prowler_delete_provider", {"provider_id": "p1"}) + + +async def test_a_deletion_task_failure_does_not_relay_the_upstream_text( + mcp_root_server, mock_api_client, mock_router +): + """The task's own error is a celery traceback; it stays in the log.""" + stub_deletion_start(mock_router) + mock_router.add( + "GET", + TASK, + json=task_document("t1", "failed", error="Traceback: secret-internal-detail"), + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception) as raised: + await client.call_tool("prowler_delete_provider", {"provider_id": "p1"}) + + assert "secret-internal-detail" not in str(raised.value) + + +async def test_a_deletion_whose_progress_cannot_be_read_still_says_do_not_retry( + mcp_root_server, mock_api_client, mock_router, mock_fast_polling +): + """The outcome is unknown, which for a destructive call means: do not repeat. + + Reading the task is what tells "still running" from "stopped", so when that + read fails too the message drops the claim rather than guessing at one. + """ + stub_deletion_start(mock_router) + mock_router.add("GET", TASK, status=503, json=jsonapi_error(503, "Unavailable.")) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_delete_provider", {"provider_id": "p1"} + ) + + assert result.data["status"] == "in_progress" + assert "could not be read" in result.data["message"] + assert "Do not send the deletion again" in result.data["message"] + # The failure that got us here is the classifier's to phrase, so its raw + # text stays in the log rather than riding along in the message. + assert "API request failed" not in result.data["message"] + + +# ------------------------------------------------------- connection check + + +async def test_a_connection_check_that_cannot_run_is_not_reported_as_failed( + mcp_root_server, mock_api_client, mock_router +): + """`not_tested` says nothing about the credentials, and that is the point. + + A 401 here is this server's own credential, not the provider's. Calling it + `failed` tells the user their AWS role is broken when it is fine. + """ + # Registered in order and consumed in order: the lookup before the create + # finds nothing, the one after it finds the provider that was just made. + mock_router.add("GET", PROVIDERS, json=jsonapi_collection([])) + mock_router.add( + "GET", + PROVIDERS, + json=jsonapi_collection( + [jsonapi_resource("providers", "p1", PROVIDER_ATTRIBUTES)] + ), + ) + mock_router.add( + "POST", + PROVIDERS, + json=jsonapi_document(jsonapi_resource("providers", "p1", PROVIDER_ATTRIBUTES)), + ) + mock_router.add( + "POST", CONNECTION, status=401, json=jsonapi_error(401, "Token expired.") + ) + mock_router.add( + "GET", + PROVIDER, + json=jsonapi_document(jsonapi_resource("providers", "p1", PROVIDER_ATTRIBUTES)), + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_connect_provider", + {"provider_uid": "123456789012", "provider_type": "aws"}, + ) + + assert result.data["connected"] == "not_tested" + assert "never tested" in result.data["error"] + + +async def test_a_secret_lookup_failure_does_not_pass_as_having_no_secret( + mcp_root_server, mock_api_client, mock_router +): + """Returning None here would send the write down the create branch. + + A provider holds at most one secret, so creating a second one is refused and + the caller would be told its credentials were rejected when all that + actually failed was this read. + """ + mock_router.add( + "GET", + PROVIDERS, + json=jsonapi_collection( + [jsonapi_resource("providers", "p1", PROVIDER_ATTRIBUTES)] + ), + ) + mock_router.add( + "GET", SECRETS, status=429, json=jsonapi_error(429, "Too many requests.") + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="rate limiting"): + await client.call_tool( + "prowler_connect_provider", + { + "provider_uid": "123456789012", + "provider_type": "aws", + "credentials": { + "aws_access_key_id": "AKIA", + "aws_secret_access_key": "s", + }, + }, + ) + + assert f"POST {SECRETS}" not in mock_router.paths() diff --git a/mcp_server/tests/prowler_app/tools/test_roles.py b/mcp_server/tests/prowler_app/tools/test_roles.py new file mode 100644 index 0000000000..f792cf0a04 --- /dev/null +++ b/mcp_server/tests/prowler_app/tools/test_roles.py @@ -0,0 +1,147 @@ +"""Tests for the role (RBAC) tools. + +``prowler_set_user_role`` replaces the single role a user holds, and the API +silently drops a role ID that does not exist in the tenant -- which would leave +the user with no role at all. So the tool reads the role first, and what that +read says has to be told apart carefully: only a not-found is about the role ID +the caller passed. A permission error, a rate limit or a server error is about +the request, and reporting either as "find a valid role ID" sends the user to +fix an ID that was fine. + +Tools are driven through an in-memory MCP client so FastMCP resolves the +pydantic ``Field`` defaults and a raised failure arrives the way a client sees +it. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.http import MockRouter +from tests.helpers.jsonapi import ( + jsonapi_document, + jsonapi_error, + jsonapi_resource, +) + +USER = "/api/v1/users/u1" +USER_ROLES = f"{USER}/relationships/roles" +ROLE = "/api/v1/roles/r2" + +ROLE_ATTRIBUTES = {"name": "admin", "manage_account": True} + + +def stub_user_holding(mock_router: MockRouter, role_id: str) -> MockRouter: + """Serve ``GET /users/u1?include=roles`` with the user holding one role.""" + return mock_router.add( + "GET", + USER, + json=jsonapi_document( + jsonapi_resource("users", "u1", {"name": "Ada"}), + included=[jsonapi_resource("roles", role_id, ROLE_ATTRIBUTES)], + ), + ) + + +async def test_setting_a_role_the_user_already_holds_changes_nothing( + mcp_root_server, mock_api_client, mock_router +): + """Idempotent by design: no PATCH goes out, so nothing can be replaced.""" + stub_user_holding(mock_router, "r2") + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_set_user_role", {"user_id": "u1", "role_id": "r2"} + ) + + assert result.data["changed"] is False + assert mock_router.paths() == [f"GET {USER}"] + + +async def test_a_role_that_does_not_exist_is_named_as_the_bad_argument( + mcp_root_server, mock_api_client, mock_router +): + """404 is the one answer that really is about the role ID. + + The PATCH would accept the ID and drop it, leaving the user with no role, so + the read has to stop the call -- and say which ID to replace. + """ + stub_user_holding(mock_router, "r1") + mock_router.add("GET", ROLE, status=404, json=jsonapi_error(404, "Not found.")) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="does not exist in this tenant") as raised: + await client.call_tool( + "prowler_set_user_role", {"user_id": "u1", "role_id": "r2"} + ) + + assert "left unchanged" in str(raised.value) + assert f"PATCH {USER_ROLES}" not in mock_router.paths() + + +@pytest.mark.parametrize( + ("status", "detail", "expected"), + [ + (403, "Not allowed.", "not allowed to do this"), + (429, "Slow down.", "rate limiting"), + (500, "Boom.", "failed on Prowler's side"), + ], + ids=["forbidden", "rate-limited", "server-error"], +) +async def test_a_role_read_that_failed_for_another_reason_is_not_a_bad_role_id( + mcp_root_server, mock_api_client, mock_router, status, detail, expected +): + """These say nothing about the ID, so the classifier owns the message. + + Told "use prowler_list_roles to find a valid role ID", an agent goes looking + for a role that was never the problem -- and finds the same wall. + """ + stub_user_holding(mock_router, "r1") + mock_router.add("GET", ROLE, status=status, json=jsonapi_error(status, detail)) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match=expected) as raised: + await client.call_tool( + "prowler_set_user_role", {"user_id": "u1", "role_id": "r2"} + ) + + assert "valid role ID" not in str(raised.value) + assert f"PATCH {USER_ROLES}" not in mock_router.paths() + + +async def test_a_set_role_reports_the_role_the_user_holds_afterwards( + mcp_root_server, mock_api_client, mock_router +): + """The authoritative state is read back rather than assumed from the PATCH.""" + mock_router.add( + "GET", + USER, + json=jsonapi_document( + jsonapi_resource("users", "u1", {"name": "Ada"}), + included=[jsonapi_resource("roles", "r1", ROLE_ATTRIBUTES)], + ), + ) + mock_router.add( + "GET", + USER, + json=jsonapi_document( + jsonapi_resource("users", "u1", {"name": "Ada"}), + included=[jsonapi_resource("roles", "r2", ROLE_ATTRIBUTES)], + ), + ) + mock_router.add( + "GET", + ROLE, + json=jsonapi_document(jsonapi_resource("roles", "r2", ROLE_ATTRIBUTES)), + ) + mock_router.add("PATCH", USER_ROLES, status=204) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_set_user_role", {"user_id": "u1", "role_id": "r2"} + ) + + assert result.data["changed"] is True + assert [role["id"] for role in result.data["roles"]] == ["r2"] + assert mock_router.json_body("PATCH", USER_ROLES) == { + "data": [{"type": "roles", "id": "r2"}] + } diff --git a/mcp_server/tests/prowler_app/tools/test_scans.py b/mcp_server/tests/prowler_app/tools/test_scans.py new file mode 100644 index 0000000000..93e18c9a69 --- /dev/null +++ b/mcp_server/tests/prowler_app/tools/test_scans.py @@ -0,0 +1,201 @@ +"""Tests for the scans tools. + +Both write tools here used to answer a failure with a result object that the +protocol, the client and the model all read as a success, and both are calls +whose outcome an agent acts on: + +* ``prowler_trigger_scan`` starts work. Anything that reads as "nothing + happened" invites a second scan of the same provider. +* ``prowler_schedule_daily_scan`` was deciding whether the schedule existed by + reading the state of a different thing entirely -- the first scan Prowler + starts alongside it -- so a schedule that had just been created could be + reported as a failure. Retrying that can only hit the 409 the API raises for a + provider that already has one. + +Tools are driven through an in-memory MCP client so FastMCP resolves the +pydantic ``Field`` defaults and a raised failure arrives the way a client sees +it. +""" + +import pytest +from fastmcp import Client + +from tests.helpers.http import MockRouter +from tests.helpers.jsonapi import ( + jsonapi_document, + jsonapi_error, + jsonapi_resource, +) + +SCANS = "/api/v1/scans" +SCAN = f"{SCANS}/s1" +DAILY = "/api/v1/schedules/daily" + +SCAN_ATTRIBUTES = { + "name": "Nightly", + "trigger": "manual", + "state": "executing", + "progress": 40, +} + + +def stub_scan_creation(mock_router: MockRouter, scan_id: str = "s1") -> MockRouter: + """Serve the creation as Prowler does: a task carrying the new scan's ID.""" + return mock_router.add( + "POST", + SCANS, + json=jsonapi_document( + jsonapi_resource("tasks", "t1", {"task_args": {"scan_id": scan_id}}) + ), + ) + + +# ------------------------------------------------------------- trigger_scan + + +async def test_a_refused_scan_is_an_error_not_a_failed_looking_result( + mcp_root_server, mock_api_client, mock_router +): + """A rejection has to leave the tool as an error. + + Returned as a result it arrives with ``isError: false``, and a model reading + a successful tool call has no reason to doubt that a scan is now running. + """ + mock_router.add( + "POST", SCANS, status=403, json=jsonapi_error(403, "Insufficient permissions.") + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="not allowed to do this"): + await client.call_tool("prowler_trigger_scan", {"provider_id": "p1"}) + + +async def test_a_scan_with_no_id_back_warns_before_a_blind_retry( + mcp_root_server, mock_api_client, mock_router +): + """Prowler accepted it, so a second call could start a duplicate scan. + + The message names the provider because that is what makes the suggested + check actionable without another lookup. + """ + mock_router.add("POST", SCANS, json={"data": {"attributes": {"task_args": {}}}}) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="did not return its ID"): + await client.call_tool("prowler_trigger_scan", {"provider_id": "p1"}) + + assert mock_router.paths() == [f"POST {SCANS}"] + + +async def test_a_scan_whose_read_back_fails_still_hands_over_the_id( + mcp_root_server, mock_api_client, mock_router +): + """The scan is running; only reading it back went wrong. + + Reporting the read failure alone would read as "the scan was not created" + and invite a duplicate, so the error carries the ID to monitor instead. + """ + stub_scan_creation(mock_router) + mock_router.add("GET", SCAN, status=400, json=jsonapi_error(400, "Server error.")) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="Scan s1 was created") as raised: + await client.call_tool("prowler_trigger_scan", {"provider_id": "p1"}) + + # Naming the scan is the whole reason this message exists, so it is written + # here rather than assembled from the failure. Splicing the failure text in + # would put whatever it happens to say in front of the model unclassified, + # which is the one thing the shared classifier exists to decide. + assert "API request failed" not in str(raised.value) + + +async def test_a_created_scan_comes_back_with_its_details( + mcp_root_server, mock_api_client, mock_router +): + """The success path still reports the scan, which is what gets monitored.""" + stub_scan_creation(mock_router) + mock_router.add( + "GET", + SCAN, + json=jsonapi_document(jsonapi_resource("scans", "s1", SCAN_ATTRIBUTES)), + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool("prowler_trigger_scan", {"provider_id": "p1"}) + + assert result.data["scan"]["id"] == "s1" + # No status flag: a scan that was not created is raised, so "success" could + # only ever be the one value and says nothing a reader can act on. + assert "status" not in result.data + + +# ------------------------------------------------------ schedule_daily_scan + + +@pytest.mark.parametrize("first_run_state", ["available", "scheduled", "executing"]) +async def test_a_schedule_is_reported_created_whatever_the_first_run_does( + mcp_root_server, mock_api_client, mock_router, first_run_state +): + """The task in the answer is the first scan run, not the schedule. + + Prowler commits the recurring schedule inside the request that serves this + call, so an answer at all means it exists. Reading that task's state as the + outcome of the scheduling reported a schedule that had just been created as + a failure. + """ + mock_router.add( + "POST", + DAILY, + json=jsonapi_document( + jsonapi_resource("tasks", "t1", {"state": first_run_state}) + ), + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_schedule_daily_scan", {"provider_id": "p1"} + ) + + assert result.data["first_run_state"] == first_run_state + assert "every 24 hours" in result.data["message"] + assert "scheduled" not in result.data + + +async def test_a_failed_first_run_leaves_the_schedule_standing( + mcp_root_server, mock_api_client, mock_router +): + """Worth saying, but it is not the schedule that failed. + + The gap it leaves is real -- no findings until tomorrow -- so the message + points at the manual scan that fills it rather than at the scheduling. + """ + mock_router.add( + "POST", + DAILY, + json=jsonapi_document(jsonapi_resource("tasks", "t1", {"state": "failed"})), + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_schedule_daily_scan", {"provider_id": "p1"} + ) + + assert result.data["first_run_state"] == "failed" + assert "schedule is unaffected" in result.data["message"] + assert "prowler_trigger_scan" in result.data["message"] + + +async def test_an_existing_schedule_is_relayed_as_the_api_explains_it( + mcp_root_server, mock_api_client, mock_router +): + """The 409 already says the useful thing, so the classifier relays it.""" + mock_router.add( + "POST", + DAILY, + status=409, + json=jsonapi_error(409, "There is already a scheduled scan for this provider."), + ) + + async with Client(mcp_root_server) as client: + with pytest.raises(Exception, match="already a scheduled scan"): + await client.call_tool("prowler_schedule_daily_scan", {"provider_id": "p1"}) diff --git a/mcp_server/tests/prowler_app/utils/test_auth.py b/mcp_server/tests/prowler_app/utils/test_auth.py index d39e5826d7..3c822cf2dc 100644 --- a/mcp_server/tests/prowler_app/utils/test_auth.py +++ b/mcp_server/tests/prowler_app/utils/test_auth.py @@ -6,8 +6,12 @@ Reference for later branches: ``ProwlerAppAuth`` resolves its ``mode`` and and ``base_url=`` explicitly, as these tests do. """ +import base64 +import json + import pytest +from prowler_mcp_server.lib.errors import CredentialError from prowler_mcp_server.prowler_app.utils.auth import ProwlerAppAuth from tests.helpers.tokens import FAKE_API_KEY, MALFORMED_API_KEY, fake_jwt @@ -42,13 +46,92 @@ async def test_http_mode_accepts_a_bearer_api_key(http_request_headers): assert await auth.get_valid_token() == FAKE_API_KEY +def _jwt_with_payload(payload: object) -> str: + """Mint an unsigned JWT carrying an arbitrary payload. + + ``fake_jwt`` always writes a well-formed object, so the malformed payloads + below are built here instead. + """ + encoded = ( + base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=") + ) + return f"header.{encoded}.fake-signature-not-verified" + + +async def test_http_mode_accepts_a_lowercase_bearer_scheme(http_request_headers): + """Authentication scheme names are case-insensitive (RFC 7235).""" + http_request_headers(authorization=f"bearer {FAKE_API_KEY}") + + auth = ProwlerAppAuth(mode="http") + + assert await auth.get_valid_token() == FAKE_API_KEY + + +async def test_http_mode_strips_only_the_scheme_prefix(http_request_headers): + """A token that repeats the scheme keeps it: only the prefix is removed.""" + token = f"{FAKE_API_KEY}_Bearer_suffix" + http_request_headers(authorization=f"Bearer {token}") + + auth = ProwlerAppAuth(mode="http") + + assert await auth.get_valid_token() == token + + +async def test_http_mode_rejects_an_authorization_header_without_a_token( + http_request_headers, +): + """A bare scheme carries no credential to authenticate with.""" + http_request_headers(authorization="Bearer ") + + auth = ProwlerAppAuth(mode="http") + + with pytest.raises(CredentialError, match="'Bearer ' form"): + await auth.get_valid_token() + + +async def test_http_mode_rejects_a_jwt_whose_payload_is_not_an_object( + http_request_headers, +): + """A payload that decodes to a list has no claims, so it is a bad credential. + + Without the type check it would reach `payload.get` and fail as an + unclassified `AttributeError`, which the client only sees masked. + """ + http_request_headers(authorization=f"Bearer {_jwt_with_payload(['exp'])}") + + auth = ProwlerAppAuth(mode="http") + + with pytest.raises(CredentialError, match="not a readable JWT"): + await auth.get_valid_token() + + +@pytest.mark.parametrize( + ("payload", "case"), + [ + ({"sub": "user"}, "missing"), + ({"exp": "1700000000"}, "string"), + ({"exp": None}, "null"), + ], +) +async def test_http_mode_rejects_a_jwt_without_a_numeric_expiration( + http_request_headers, payload: dict, case: str +): + """`exp` is a numeric date: comparing anything else raises a `TypeError`.""" + http_request_headers(authorization=f"Bearer {_jwt_with_payload(payload)}") + + auth = ProwlerAppAuth(mode="http") + + with pytest.raises(CredentialError, match="no readable 'exp' expiration claim"): + await auth.get_valid_token() + + async def test_http_mode_rejects_an_expired_jwt(http_request_headers): """An expired JWT is refused locally instead of being forwarded to the API.""" http_request_headers(authorization=f"Bearer {fake_jwt(expires_in=-60)}") auth = ProwlerAppAuth(mode="http") - with pytest.raises(ValueError, match="Token has expired"): + with pytest.raises(CredentialError, match="The token has expired"): await auth.get_valid_token() From 1679094f22bbb9029a56ea524189d487b3d8be3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Mon, 31 Aug 2026 13:09:34 +0200 Subject: [PATCH 06/77] feat(mcp): raise instead of returning error objects in the Prowler Hub tools (#12533) --- .../mcp-hub-check-provider-mismatch.fixed.md | 1 + mcp_server/prowler_mcp_server/lib/errors.py | 64 ++ mcp_server/prowler_mcp_server/lib/urls.py | 36 + .../prowler_mcp_server/prowler_hub/server.py | 679 ++++++++++-------- mcp_server/tests/lib/test_errors.py | 78 ++ mcp_server/tests/lib/test_urls.py | 59 ++ mcp_server/tests/prowler_hub/test_server.py | 335 +++++++++ 7 files changed, 949 insertions(+), 303 deletions(-) create mode 100644 mcp_server/changelog.d/mcp-hub-check-provider-mismatch.fixed.md create mode 100644 mcp_server/prowler_mcp_server/lib/urls.py create mode 100644 mcp_server/tests/lib/test_urls.py create mode 100644 mcp_server/tests/prowler_hub/test_server.py diff --git a/mcp_server/changelog.d/mcp-hub-check-provider-mismatch.fixed.md b/mcp_server/changelog.d/mcp-hub-check-provider-mismatch.fixed.md new file mode 100644 index 0000000000..da39e914b1 --- /dev/null +++ b/mcp_server/changelog.d/mcp-hub-check-provider-mismatch.fixed.md @@ -0,0 +1 @@ +`prowler_hub_get_check_code` and `prowler_hub_get_check_fixer` now report a check ID that belongs to another provider as such, naming that provider, instead of reporting the ID as one that does not exist diff --git a/mcp_server/prowler_mcp_server/lib/errors.py b/mcp_server/prowler_mcp_server/lib/errors.py index 9491bf87eb..1aa3a25607 100644 --- a/mcp_server/prowler_mcp_server/lib/errors.py +++ b/mcp_server/prowler_mcp_server/lib/errors.py @@ -55,6 +55,59 @@ class ProwlerAPIInvalidResponse(Exception): """The API answered, but with a body this server could not read as JSON.""" +class UpstreamInvalidResponse(Exception): + """An upstream this server reads directly answered with a body that is not JSON. + + Raised in place of the `json.JSONDecodeError` httpx would otherwise let out. + That one is a ValueError this module reads as a malformed argument, which is + the opposite story: it sends a model off to fix a call that was fine. + + Attributes: + host: Host that answered, so the message can name what has to be fixed + """ + + def __init__(self, message: str, *, host: str) -> None: + super().__init__(message) + self.host: str = host + + +def parse_json_response(response: httpx.Response) -> Any: + """Parse an upstream answer as JSON, telling an unreadable body from a bad + argument. + + For every upstream a sub-server reads with an httpx client of its own -- + Prowler Hub, the documentation site. `httpx` lets a body it cannot decode + out as a `json.JSONDecodeError`, which is a ValueError this module reads as + a malformed argument. Coming from an upstream -- an HTML error page from an + edge, a truncated body -- that is the wrong story, and the caller has no + argument to fix. + + The Prowler API client parses its own answers and raises + `ProwlerAPIInvalidResponse` instead: it also carries writes, where an + unreadable answer leaves the outcome unknown rather than merely absent. + + Args: + response: The answer to parse. + + Returns: + The parsed body. + + Raises: + UpstreamInvalidResponse: The body is not JSON. + """ + try: + return response.json() + except ValueError as e: + # `.request` raises rather than returning None when it was never set. + request = getattr(response, "_request", None) + host = request.url.host if request is not None else "The upstream service" + # Status only: the decoder's own message quotes the body it choked on, + # and that body is the upstream text this server never relays. + raise UpstreamInvalidResponse( + f"{response.status_code} body is not JSON", host=host + ) from e + + def jsonapi_detail(response: httpx.Response) -> str | None: """Return the API's own JSON:API error detail, when there is one to trust. @@ -171,6 +224,17 @@ def _describe_failure(exc: BaseException) -> str | None: "current state before sending it again." ) + if isinstance(exc, UpstreamInvalidResponse): + # The counterpart of the `json.JSONDecodeError` branch below: the same + # decode failure is a malformed argument on one side of this server and + # an upstream fault on the other, and only the type tells them apart. + return ( + f"{exc.host} answered with a body this server could not read as JSON, " + "so the call has no result to return. Nothing in the arguments caused " + f"this and changing them will not help -- {exc.host} is answering with " + "something other than the JSON it documents. Retry later." + ) + if isinstance(exc, CredentialError): # Not an argument problem, so it is worth saying that plainly: the # answer is a credential the user has to fix, not another attempt. diff --git a/mcp_server/prowler_mcp_server/lib/urls.py b/mcp_server/prowler_mcp_server/lib/urls.py new file mode 100644 index 0000000000..0c24a04417 --- /dev/null +++ b/mcp_server/prowler_mcp_server/lib/urls.py @@ -0,0 +1,36 @@ +"""URL construction shared by every sub-server. + +An identifier joined into a path unencoded is not sent as itself: httpx resolves +the URL per RFC 3986, so "../" walks the request onto another endpoint. +""" + +from urllib.parse import quote + +_DOT_SEGMENTS = frozenset({".", ".."}) + + +def path_segment(value: str) -> str: + """Encode one path segment, so an identifier names a resource and nothing else. + + Args: + value: The segment to encode, taken as a name in full. + + Returns: + The segment percent-encoded, with the dots escaped when it is only dots. + """ + encoded = quote(value, safe="") + # A dot is legal in a name, so `quote` keeps it: a segment of nothing but + # dots would still resolve away rather than name anything. + return encoded.replace(".", "%2E") if encoded in _DOT_SEGMENTS else encoded + + +def url_path(*segments: str) -> str: + """Build a URL path from one argument per segment, each of them encoded. + + Args: + *segments: The path segments, in order. + + Returns: + The joined path, with a leading slash. + """ + return "/" + "/".join(path_segment(segment) for segment in segments) diff --git a/mcp_server/prowler_mcp_server/prowler_hub/server.py b/mcp_server/prowler_mcp_server/prowler_hub/server.py index 8d18a2c240..2c78ac7c36 100644 --- a/mcp_server/prowler_mcp_server/prowler_hub/server.py +++ b/mcp_server/prowler_mcp_server/prowler_hub/server.py @@ -6,13 +6,19 @@ Provides access to Prowler Hub API for security checks and compliance frameworks import httpx from fastmcp import FastMCP +from fastmcp.exceptions import ToolError from pydantic import Field from prowler_mcp_server import __version__ +from prowler_mcp_server.lib.errors import ( + UpstreamInvalidResponse, + parse_json_response, +) from prowler_mcp_server.lib.types import NonBlankStr +from prowler_mcp_server.lib.urls import url_path # Initialize FastMCP for Prowler Hub -hub_mcp_server = FastMCP("prowler-hub") +hub_mcp_server = FastMCP("prowler-hub", mask_error_details=True) # API base URL BASE_URL = "https://hub.prowler.com/api" @@ -27,6 +33,19 @@ prowler_hub_client = httpx.Client( }, ) +# Sentences for the not-found cases. They are authored here, and raised as a +# ToolError without a `from` clause, because they name the resource the caller +# asked for and the next tool to reach for -- neither of which the shared +# classifier in lib/errors.py can know. +_CHECK_NOT_FOUND = ( + "No check with the ID '{check_id}' exists in Prowler Hub. Use " + "prowler_hub_semantic_search_checks to find the right ID." +) +_COMPLIANCE_NOT_FOUND = ( + "No compliance framework with the ID '{compliance_id}' exists in Prowler Hub. " + "Use prowler_hub_semantic_search_compliances to find the right ID." +) + # GitHub raw content base URL for Prowler checks GITHUB_RAW_BASE = ( "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/heads/master/" @@ -43,6 +62,21 @@ github_raw_client = httpx.Client( ) +def _get_hub_endpoint( + *path_segments: str, params: dict[str, str] | None = None +) -> httpx.Response: + """GET a Prowler Hub endpoint, named as one argument per path segment. + + Args: + *path_segments: The endpoint path segments, in order. + params: Query parameters for the request. + + Returns: + The response unread, so a caller can tell a 404 from a failed request. + """ + return prowler_hub_client.get(url_path(*path_segments), params=params) + + def github_check_path(provider_id: str, check_id: str, suffix: str) -> str: """Build the GitHub raw URL for a given check artifact suffix using provider and check_id. @@ -53,7 +87,83 @@ def github_check_path(provider_id: str, check_id: str, suffix: str) -> str: service_id = check_id.split("_", 1)[0] except IndexError: service_id = check_id - return f"{GITHUB_RAW_BASE}/{provider_id}/services/{service_id}/{check_id}/{check_id}{suffix}" + path = url_path(provider_id, "services", service_id, check_id, check_id) + return f"{GITHUB_RAW_BASE}{path}{suffix}" + + +def _hub_provider_for_check(check_id: str) -> str | None: + """Ask Prowler Hub which provider it lists a check under. + + Args: + check_id: Check ID the caller asked for + + Returns: + The provider the Hub lists the check under, or None when the Hub knows + no such check. + + Raises: + httpx.HTTPError: The Hub could not be reached. + UpstreamInvalidResponse: The Hub answered with a body that is not JSON. + ValueError: The Hub answered with something that names no provider. + """ + response = _get_hub_endpoint("check", check_id) + if response.status_code == 404: + return None + response.raise_for_status() + check = parse_json_response(response) + + # An empty body is how the Hub reports an unknown ID on some routes, so it + # is read the same way get_check_details reads it: no such check. + if not isinstance(check, dict) or not check: + return None + + provider = check.get("provider") + if isinstance(provider, str) and provider.strip(): + return provider + # A check the Hub returned without a provider tells us nothing about the + # provider the caller asked for, so it counts as unanswered rather than as + # a check that does not exist. + raise ValueError(f"Prowler Hub listed check '{check_id}' without a provider") + + +def _explain_missing_check_file( + provider_id: str, + check_id: str, + *, + when_check_belongs_here: str, + when_unverified: str, +) -> str: + """Explain a 404 from GitHub for one of a check's source files. + + GitHub answers 404 to three different mistakes, an ID that exists nowhere, + an ID that exists under a different provider, and an ID that exists right + here whose file is simply absent, and cannot tell them apart. Prowler Hub + can, so it is asked before anything is claimed about the ID. + + Args: + provider_id: Provider the caller asked for + check_id: Check the caller asked for + when_check_belongs_here: Message for the case where the Hub confirms the + check does belong to this provider + when_unverified: Message for the case where the Hub could not be asked + + Returns: + The sentence to fail the tool with + """ + try: + hub_provider = _hub_provider_for_check(check_id) + except (httpx.HTTPError, UpstreamInvalidResponse, ValueError): + return when_unverified + + if hub_provider is None: + return _CHECK_NOT_FOUND.format(check_id=check_id) + if hub_provider != provider_id: + return ( + f"Provider '{provider_id}' has no check '{check_id}'. Prowler Hub lists " + f"that check under provider '{hub_provider}', so retry with " + f"provider_id='{hub_provider}'." + ) + return when_check_belongs_here # Security Check Tools @@ -123,29 +233,22 @@ async def list_checks( if compliances: params["compliances"] = ",".join(compliances) - try: - response = prowler_hub_client.get("/check", params=params) - response.raise_for_status() - checks = response.json() + response = _get_hub_endpoint("check", params=params) + response.raise_for_status() + checks = parse_json_response(response) - # Return checks as a lightweight list - checks_list = [] - for check in checks: - check_data = { - "id": check["id"], - "provider": check["provider"], - "title": check["title"], - "severity": check["severity"], - } - checks_list.append(check_data) - - return {"count": len(checks), "checks": checks_list} - except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", + # Return checks as a lightweight list + checks_list = [] + for check in checks: + check_data = { + "id": check["id"], + "provider": check["provider"], + "title": check["title"], + "severity": check["severity"], } - except Exception as e: - return {"error": str(e)} + checks_list.append(check_data) + + return {"count": len(checks), "checks": checks_list} @hub_mcp_server.tool() @@ -182,29 +285,22 @@ async def semantic_search_checks( 2. Use `prowler_hub_list_checks` with filters for more targeted browsing 3. Use `prowler_hub_get_check_details` to get complete information for a specific check """ - try: - response = prowler_hub_client.get("/check/search", params={"term": term}) - response.raise_for_status() - checks = response.json() + response = _get_hub_endpoint("check", "search", params={"term": term}) + response.raise_for_status() + checks = parse_json_response(response) - # Return checks as a lightweight list - checks_list = [] - for check in checks: - check_data = { - "id": check["id"], - "provider": check["provider"], - "title": check["title"], - "severity": check["severity"], - } - checks_list.append(check_data) - - return {"count": len(checks), "checks": checks_list} - except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", + # Return checks as a lightweight list + checks_list = [] + for check in checks: + check_data = { + "id": check["id"], + "provider": check["provider"], + "title": check["title"], + "severity": check["severity"], } - except Exception as e: - return {"error": str(e)} + checks_list.append(check_data) + + return {"count": len(checks), "checks": checks_list} @hub_mcp_server.tool() @@ -274,75 +370,75 @@ async def get_check_details( 2. Use this tool with the check 'id' to get complete information including remediation guidance """ try: - response = prowler_hub_client.get(f"/check/{check_id}") + response = _get_hub_endpoint("check", check_id) response.raise_for_status() - check = response.json() - - if not check: - return {"error": f"Check '{check_id}' not found"} - - # Build response with only non-empty fields to save tokens - result = {} - - # Core fields - result["id"] = check["id"] - if check.get("title"): - result["title"] = check["title"] - if check.get("description"): - result["description"] = check["description"] - if check.get("provider"): - result["provider"] = check["provider"] - if check.get("service"): - result["service"] = check["service"] - if check.get("severity"): - result["severity"] = check["severity"] - if check.get("risk"): - result["risk"] = check["risk"] - if check.get("resource_type"): - result["resource_type"] = check["resource_type"] - - # List fields - if check.get("reference"): - result["reference"] = check["reference"] - if check.get("additional_urls"): - result["additional_urls"] = check["additional_urls"] - if check.get("services_required"): - result["services_required"] = check["services_required"] - if check.get("categories"): - result["categories"] = check["categories"] - if check.get("compliances"): - result["compliances"] = check["compliances"] - - # Other fields - if check.get("notes"): - result["notes"] = check["notes"] - if check.get("related_url"): - result["related_url"] = check["related_url"] - if check.get("fixer") is not None: - result["fixer"] = check["fixer"] - - # Remediation - filter out empty nested values - remediation = check.get("remediation", {}) - if remediation: - filtered_remediation = {} - for key, value in remediation.items(): - if value and isinstance(value, dict): - # Filter out empty values within nested dict - filtered_value = {k: v for k, v in value.items() if v} - if filtered_value: - filtered_remediation[key] = filtered_value - elif value: - filtered_remediation[key] = value - if filtered_remediation: - result["remediation"] = filtered_remediation - - return result except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", - } - except Exception as e: - return {"error": str(e)} + if e.response.status_code == 404: + # No `from`: this names the check, which the shared classifier cannot. + raise ToolError(_CHECK_NOT_FOUND.format(check_id=check_id)) + raise + + check = parse_json_response(response) + + if not check: + raise ToolError(_CHECK_NOT_FOUND.format(check_id=check_id)) + + # Build response with only non-empty fields to save tokens + result = {} + + # Core fields + result["id"] = check["id"] + if check.get("title"): + result["title"] = check["title"] + if check.get("description"): + result["description"] = check["description"] + if check.get("provider"): + result["provider"] = check["provider"] + if check.get("service"): + result["service"] = check["service"] + if check.get("severity"): + result["severity"] = check["severity"] + if check.get("risk"): + result["risk"] = check["risk"] + if check.get("resource_type"): + result["resource_type"] = check["resource_type"] + + # List fields + if check.get("reference"): + result["reference"] = check["reference"] + if check.get("additional_urls"): + result["additional_urls"] = check["additional_urls"] + if check.get("services_required"): + result["services_required"] = check["services_required"] + if check.get("categories"): + result["categories"] = check["categories"] + if check.get("compliances"): + result["compliances"] = check["compliances"] + + # Other fields + if check.get("notes"): + result["notes"] = check["notes"] + if check.get("related_url"): + result["related_url"] = check["related_url"] + if check.get("fixer") is not None: + result["fixer"] = check["fixer"] + + # Remediation - filter out empty nested values + remediation = check.get("remediation", {}) + if remediation: + filtered_remediation = {} + for key, value in remediation.items(): + if value and isinstance(value, dict): + # Filter out empty values within nested dict + filtered_value = {k: v for k, v in value.items() if v} + if filtered_value: + filtered_remediation[key] = filtered_value + elif value: + filtered_remediation[key] = value + if filtered_remediation: + result["remediation"] = filtered_remediation + + return result @hub_mcp_server.tool() @@ -364,31 +460,38 @@ async def get_check_code( "content": "Python source code of the check implementation" } """ - if provider_id and check_id: - url = github_check_path(provider_id, check_id, ".py") - try: - resp = github_raw_client.get(url) - resp.raise_for_status() - return { - "content": resp.text, - } - except httpx.HTTPStatusError as e: - if e.response.status_code == 404: - return { - "error": f"Check {check_id} not found in Prowler", - } - else: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", - } - except Exception as e: - return { - "error": str(e), - } - else: - return { - "error": "Provider ID and check ID are required", - } + url = github_check_path(provider_id, check_id, ".py") + try: + resp = github_raw_client.get(url) + resp.raise_for_status() + except httpx.HTTPStatusError as e: + if e.response.status_code == 404: + # No `from`: this names the check and the provider that does have + # it, neither of which the shared classifier in lib/errors.py knows. + raise ToolError( + _explain_missing_check_file( + provider_id, + check_id, + when_check_belongs_here=( + f"Prowler Hub lists check '{check_id}' under provider " + f"'{provider_id}', but prowler-cloud/prowler has no source file " + "for it on the master branch. The check may have been renamed or " + "moved since the Hub last indexed it." + ), + when_unverified=( + f"Provider '{provider_id}' has no check '{check_id}' in " + "prowler-cloud/prowler, and Prowler Hub could not be asked which " + "provider does. Either the ID is wrong or the check belongs to " + "another provider, prowler_hub_get_check_details reports the " + "provider a check belongs to." + ), + ) + ) + raise + + return { + "content": resp.text, + } @hub_mcp_server.tool() @@ -402,8 +505,9 @@ async def get_check_fixer( ) -> dict: """Fetch the auto-remediation (fixer) code for a Prowler security check. - IMPORTANT: Not all checks have fixers. A "fixer not found" response means the check - doesn't have auto-remediation code - this is normal for many checks. + IMPORTANT: Not all checks have fixers. A check with no auto-remediation code fails + with a message saying so - this is normal for many checks and not a problem to + report or retry. Fixer code provides automated remediation that can fix security issues detected by checks. Use this to understand how to programmatically remediate findings. @@ -412,40 +516,37 @@ async def get_check_fixer( { "content": "Python source code of the auto-remediation implementation" } - Or if no fixer exists: - { - "error": "Fixer not found for check {check_id}" - } """ - if provider_id and check_id: - url = github_check_path(provider_id, check_id, "_fixer.py") - try: - resp = github_raw_client.get(url) - if resp.status_code == 404: - return { - "error": f"Fixer not found for check {check_id}", - } - resp.raise_for_status() - return { - "content": resp.text, - } - except httpx.HTTPStatusError as e: - if e.response.status_code == 404: - return { - "error": f"Check {check_id} not found in Prowler", - } - else: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", - } - except Exception as e: - return { - "error": str(e), - } - else: - return { - "error": "Provider ID and check ID are required", - } + url = github_check_path(provider_id, check_id, "_fixer.py") + try: + resp = github_raw_client.get(url) + resp.raise_for_status() + except httpx.HTTPStatusError as e: + if e.response.status_code == 404: + # "No fixer" is only one of the reasons the file is missing, and the + # others are the caller's to fix, so they are told apart first. + raise ToolError( + _explain_missing_check_file( + provider_id, + check_id, + when_check_belongs_here=( + f"Check {check_id} has no auto-remediation code. Many checks do " + "not, and that is normal." + ), + when_unverified=( + f"Provider '{provider_id}' has no auto-remediation code for " + f"check '{check_id}'. Many checks have none, and that is normal, " + f"but Prowler Hub could not be asked whether the check belongs " + f"to '{provider_id}' at all. Confirm it with " + "prowler_hub_get_check_details if you expected a fixer." + ), + ) + ) + raise + + return { + "content": resp.text, + } # Compliance Framework Tools @@ -492,28 +593,21 @@ async def list_compliances( if provider: params["provider"] = ",".join(provider) - try: - response = prowler_hub_client.get("/compliance", params=params) - response.raise_for_status() - compliances = response.json() + response = _get_hub_endpoint("compliance", params=params) + response.raise_for_status() + compliances = parse_json_response(response) - # Return compliances as a lightweight list - compliances_list = [] - for compliance in compliances: - compliance_data = { - "id": compliance["id"], - "name": compliance["name"], - "provider": compliance["provider"], - } - compliances_list.append(compliance_data) - - return {"count": len(compliances), "compliances": compliances_list} - except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", + # Return compliances as a lightweight list + compliances_list = [] + for compliance in compliances: + compliance_data = { + "id": compliance["id"], + "name": compliance["name"], + "provider": compliance["provider"], } - except Exception as e: - return {"error": str(e)} + compliances_list.append(compliance_data) + + return {"count": len(compliances), "compliances": compliances_list} @hub_mcp_server.tool() @@ -543,28 +637,21 @@ async def semantic_search_compliances( ] } """ - try: - response = prowler_hub_client.get("/compliance/search", params={"term": term}) - response.raise_for_status() - compliances = response.json() + response = _get_hub_endpoint("compliance", "search", params={"term": term}) + response.raise_for_status() + compliances = parse_json_response(response) - # Return compliances as a lightweight list - compliances_list = [] - for compliance in compliances: - compliance_data = { - "id": compliance["id"], - "name": compliance["name"], - "provider": compliance["provider"], - } - compliances_list.append(compliance_data) - - return {"count": len(compliances), "compliances": compliances_list} - except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", + # Return compliances as a lightweight list + compliances_list = [] + for compliance in compliances: + compliance_data = { + "id": compliance["id"], + "name": compliance["name"], + "provider": compliance["provider"], } - except Exception as e: - return {"error": str(e)} + compliances_list.append(compliance_data) + + return {"count": len(compliances), "compliances": compliances_list} @hub_mcp_server.tool() @@ -599,63 +686,60 @@ async def get_compliance_details( } """ try: - response = prowler_hub_client.get(f"/compliance/{compliance_id}") + response = _get_hub_endpoint("compliance", compliance_id) response.raise_for_status() - compliance = response.json() - - if not compliance: - return {"error": f"Compliance '{compliance_id}' not found"} - - # Build response with only non-empty fields to save tokens - result = {} - - # Core fields - result["id"] = compliance["id"] - if compliance.get("name"): - result["name"] = compliance["name"] - if compliance.get("framework"): - result["framework"] = compliance["framework"] - if compliance.get("provider"): - result["provider"] = compliance["provider"] - if compliance.get("version"): - result["version"] = compliance["version"] - if compliance.get("description"): - result["description"] = compliance["description"] - - # Numeric fields - if compliance.get("total_checks"): - result["total_checks"] = compliance["total_checks"] - if compliance.get("total_requirements"): - result["total_requirements"] = compliance["total_requirements"] - - # Requirements - filter out empty nested values - requirements = compliance.get("requirements", []) - if requirements: - filtered_requirements = [] - for req in requirements: - filtered_req = {} - if req.get("id"): - filtered_req["id"] = req["id"] - if req.get("name"): - filtered_req["name"] = req["name"] - if req.get("description"): - filtered_req["description"] = req["description"] - if req.get("checks"): - filtered_req["checks"] = req["checks"] - if filtered_req: - filtered_requirements.append(filtered_req) - if filtered_requirements: - result["requirements"] = filtered_requirements - - return result except httpx.HTTPStatusError as e: if e.response.status_code == 404: - return {"error": f"Compliance '{compliance_id}' not found"} - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", - } - except Exception as e: - return {"error": str(e)} + raise ToolError(_COMPLIANCE_NOT_FOUND.format(compliance_id=compliance_id)) + raise + + compliance = parse_json_response(response) + + if not compliance: + raise ToolError(_COMPLIANCE_NOT_FOUND.format(compliance_id=compliance_id)) + + # Build response with only non-empty fields to save tokens + result = {} + + # Core fields + result["id"] = compliance["id"] + if compliance.get("name"): + result["name"] = compliance["name"] + if compliance.get("framework"): + result["framework"] = compliance["framework"] + if compliance.get("provider"): + result["provider"] = compliance["provider"] + if compliance.get("version"): + result["version"] = compliance["version"] + if compliance.get("description"): + result["description"] = compliance["description"] + + # Numeric fields + if compliance.get("total_checks"): + result["total_checks"] = compliance["total_checks"] + if compliance.get("total_requirements"): + result["total_requirements"] = compliance["total_requirements"] + + # Requirements - filter out empty nested values + requirements = compliance.get("requirements", []) + if requirements: + filtered_requirements = [] + for req in requirements: + filtered_req = {} + if req.get("id"): + filtered_req["id"] = req["id"] + if req.get("name"): + filtered_req["name"] = req["name"] + if req.get("description"): + filtered_req["description"] = req["description"] + if req.get("checks"): + filtered_req["checks"] = req["checks"] + if filtered_req: + filtered_requirements.append(filtered_req) + if filtered_requirements: + result["requirements"] = filtered_requirements + + return result # Provider Tools @@ -684,27 +768,20 @@ async def list_providers() -> dict: ] } """ - try: - response = prowler_hub_client.get("/providers") - response.raise_for_status() - providers = response.json() + response = _get_hub_endpoint("providers") + response.raise_for_status() + providers = parse_json_response(response) - providers_list = [] - for provider in providers: - providers_list.append( - { - "id": provider["id"], - "name": provider.get("name", ""), - } - ) + providers_list = [] + for provider in providers: + providers_list.append( + { + "id": provider["id"], + "name": provider.get("name", ""), + } + ) - return {"count": len(providers), "providers": providers_list} - except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", - } - except Exception as e: - return {"error": str(e)} + return {"count": len(providers), "providers": providers_list} @hub_mcp_server.tool() @@ -728,24 +805,20 @@ async def get_provider_services( "services": ["s3", "ec2", "iam", "rds", "lambda", ...] } """ - try: - response = prowler_hub_client.get("/providers") - response.raise_for_status() - providers = response.json() + response = _get_hub_endpoint("providers") + response.raise_for_status() + providers = parse_json_response(response) - for provider in providers: - if provider["id"] == provider_id: - return { - "provider_id": provider["id"], - "provider_name": provider.get("name", ""), - "count": len(provider.get("services", [])), - "services": provider.get("services", []), - } + for provider in providers: + if provider["id"] == provider_id: + return { + "provider_id": provider["id"], + "provider_name": provider.get("name", ""), + "count": len(provider.get("services", [])), + "services": provider.get("services", []), + } - return {"error": f"Provider '{provider_id}' not found"} - except httpx.HTTPStatusError as e: - return { - "error": f"HTTP error {e.response.status_code}: {e.response.text}", - } - except Exception as e: - return {"error": str(e)} + known = ", ".join(sorted(str(provider["id"]) for provider in providers)) + raise ToolError( + f"Prowler has no provider with the ID '{provider_id}'. Available: {known}." + ) diff --git a/mcp_server/tests/lib/test_errors.py b/mcp_server/tests/lib/test_errors.py index cd32752b42..a682034bc8 100644 --- a/mcp_server/tests/lib/test_errors.py +++ b/mcp_server/tests/lib/test_errors.py @@ -7,6 +7,7 @@ reaches a model is text this server produced. import json +import httpx import pytest from fastmcp import Client from pydantic import BaseModel, ValidationError @@ -14,7 +15,9 @@ from pydantic import BaseModel, ValidationError from prowler_mcp_server.lib.errors import ( CredentialError, InvalidArgument, + UpstreamInvalidResponse, _describe_failure, + parse_json_response, ) from prowler_mcp_server.prowler_app.utils.api_client import ( ProwlerAPIError, @@ -26,6 +29,42 @@ from tests.helpers.jsonapi import jsonapi_error LATEST = "/api/v1/findings/latest" +# --------------------------------------------------------------- json bodies + + +def _answer( + body: str, *, url: str = "https://hub.prowler.com/api/check" +) -> httpx.Response: + """An answer as a client would hand it back, request attached.""" + return httpx.Response(200, text=body, request=httpx.Request("GET", url)) + + +def test_a_json_body_is_returned_as_it_is(): + """The helper only classifies the failure; the success path is untouched.""" + assert parse_json_response(_answer('{"id": "s3_bucket_public_access"}')) == { + "id": "s3_bucket_public_access" + } + + +def test_a_body_that_is_not_json_names_the_host_that_answered(): + """Which upstream is misbehaving is the one useful fact here, and the shared + helper is reached from every sub-server that reads an upstream directly.""" + with pytest.raises(UpstreamInvalidResponse) as raised: + parse_json_response(_answer("502 Bad Gateway")) + + assert raised.value.host == "hub.prowler.com" + assert "Bad Gateway" not in str(raised.value) + + +def test_a_body_that_is_not_json_is_not_a_valueerror(): + """`JSONDecodeError` is a ValueError, and callers tell an upstream fault from + a bad argument by type alone.""" + with pytest.raises(UpstreamInvalidResponse) as raised: + parse_json_response(_answer("not json")) + + assert not isinstance(raised.value, ValueError) + + # ------------------------------------------------------------ classification @@ -94,6 +133,29 @@ def test_an_unreadable_api_answer_is_never_called_safe_to_repeat(): assert "check the current state" in message +def test_an_unreadable_upstream_answer_is_not_blamed_on_the_arguments(): + """A `JSONDecodeError` from an upstream and one from an argument are the same + exception and opposite instructions.""" + message = _describe_failure( + UpstreamInvalidResponse("200 body is not JSON", host="hub.prowler.com") + ) + + assert "hub.prowler.com" in message + assert "could not read as JSON" in message + assert "changing them will not help" in message + + +def test_an_unreadable_upstream_answer_never_quotes_the_body(): + """The body is someone else's text, so only the host and the status leave here.""" + message = _describe_failure( + UpstreamInvalidResponse( + "502 body is not JSON", host="raw.githubusercontent.com" + ) + ) + + assert "body is not JSON" not in message + + def test_an_argument_this_server_rejected_is_repeated_verbatim(): """`InvalidArgument` exists to mark a message as one we wrote.""" message = _describe_failure( @@ -227,3 +289,19 @@ async def test_a_tool_specific_message_survives_masking( assert result.isError is True assert "prowler_list_integrations" in result.content[0].text + + +async def test_a_hub_tool_failure_says_which_host_refused_it( + mcp_root_server, hub_router +): + """Hub failures arrive as raw httpx errors: host and status relayed, body not.""" + hub_router.add( + "GET", "/api/check", status=503, text="upstream nginx 10.1.2.3" + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp("prowler_hub_list_checks", {}) + + assert result.isError is True + assert "hub.prowler.com" in result.content[0].text + assert "10.1.2.3" not in result.content[0].text diff --git a/mcp_server/tests/lib/test_urls.py b/mcp_server/tests/lib/test_urls.py new file mode 100644 index 0000000000..64798d5445 --- /dev/null +++ b/mcp_server/tests/lib/test_urls.py @@ -0,0 +1,59 @@ +"""Tests for the shared URL path builder. + +The bug these pin: an identifier interpolated into a path was resolved away by +httpx per RFC 3986, so "../" reached an endpoint no tool meant to call. +""" + +import pytest + +from prowler_mcp_server.lib.urls import path_segment, url_path + + +@pytest.mark.parametrize( + ("value", "expected"), + [ + ("s3_bucket_public_access", "s3_bucket_public_access"), + ("cis_4.0_aws", "cis_4.0_aws"), + ("../../evil", "..%2F..%2Fevil"), + ("....//evil", "....%2F%2Fevil"), + ("%2e%2e%2f", "%252e%252e%252f"), + ("..;/", "..%3B%2F"), + ("s3/../evil", "s3%2F..%2Fevil"), + ("evil?fields=all", "evil%3Ffields%3Dall"), + ("evil#frag", "evil%23frag"), + ("evil\\wrong", "evil%5Cwrong"), + ("two words", "two%20words"), + ], + ids=[ + "plain", + "dots-in-a-name", + "traversal", + "stripped-filter-bypass", + "already-encoded", + "path-parameter", + "mid-path", + "query", + "fragment", + "backslash", + "space", + ], +) +def test_a_segment_survives_as_a_name_and_never_as_syntax(value, expected): + """A real ID passes through untouched; URL syntax comes back as characters.""" + assert path_segment(value) == expected + + +@pytest.mark.parametrize("value", [".", ".."], ids=["here", "up-one"]) +def test_a_segment_of_nothing_but_dots_is_escaped_rather_than_left_to_resolve(value): + """`quote` keeps a dot, so a segment of only dots would still resolve away.""" + assert path_segment(value) == value.replace(".", "%2E") + + +def test_a_path_is_the_segments_it_was_given_and_no_others(): + """One argument per segment, so no call site has to encode anything.""" + assert url_path("users", "../../evil", "roles") == "/users/..%2F..%2Fevil/roles" + + +def test_a_single_segment_path_keeps_its_leading_slash(): + """Every caller joins this onto a base URL that ends without a slash.""" + assert url_path("providers") == "/providers" diff --git a/mcp_server/tests/prowler_hub/test_server.py b/mcp_server/tests/prowler_hub/test_server.py new file mode 100644 index 0000000000..50711aa1fa --- /dev/null +++ b/mcp_server/tests/prowler_hub/test_server.py @@ -0,0 +1,335 @@ +"""Tests for the Prowler Hub tools. + +The Hub sub-server uses its own httpx clients, so its failures never pass through +the Prowler API client. They still have to arrive as tool errors rather than as a +result object, which the protocol, the client and the model all read as a success. +""" + +import pytest +from fastmcp import Client + +CHECKS = "/api/check" +PROVIDERS = "/api/providers" +COMPLIANCE = "/api/compliance" +CHECK_ID = "s3_bucket_public_access" +HUB_CHECK = f"{CHECKS}/{CHECK_ID}" + + +def github_check(provider: str, suffix: str = ".py") -> str: + """The raw.githubusercontent path a check artifact is fetched from.""" + return ( + f"/prowler-cloud/prowler/refs/heads/master/prowler/providers/{provider}" + f"/services/s3/{CHECK_ID}/{CHECK_ID}{suffix}" + ) + + +GITHUB_CHECK = github_check("aws") +GITHUB_FIXER = github_check("aws", "_fixer.py") + + +async def test_listing_checks_returns_the_lightweight_shape( + mcp_root_server, hub_router +): + """The happy path, so the failure tests below are not the only coverage.""" + hub_router.add( + "GET", + CHECKS, + json=[ + { + "id": "s3_bucket_public_access", + "provider": "aws", + "title": "S3 buckets should block public access", + "severity": "high", + } + ], + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool("prowler_hub_list_checks", {}) + + assert result.data["count"] == 1 + assert result.data["checks"][0]["id"] == "s3_bucket_public_access" + + +async def test_an_unknown_check_fails_and_names_the_tool_that_finds_one( + mcp_root_server, hub_router +): + """A 404 is the caller's mistake, and the fix is a different tool.""" + hub_router.add("GET", f"{CHECKS}/nope", status=404) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_details", {"check_id": "nope"} + ) + + assert result.isError is True + assert "prowler_hub_semantic_search_checks" in result.content[0].text + + +async def test_an_unknown_provider_fails_and_lists_the_real_ones( + mcp_root_server, hub_router +): + """The valid values are already in hand, so withholding them wastes a call.""" + hub_router.add( + "GET", + PROVIDERS, + json=[{"id": "aws", "name": "Amazon Web Services", "services": ["s3"]}], + ) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_provider_services", {"provider_id": "alicloud"} + ) + + assert result.isError is True + assert "aws" in result.content[0].text + + +async def test_a_check_without_a_fixer_says_that_is_normal(mcp_root_server, hub_router): + """Most checks have no auto-remediation, so this must not read as a defect.""" + hub_router.add("GET", GITHUB_FIXER, status=404) + hub_router.add("GET", HUB_CHECK, json={"id": CHECK_ID, "provider": "aws"}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_fixer", + {"provider_id": "aws", "check_id": CHECK_ID}, + ) + + assert result.isError is True + message = result.content[0].text + assert "normal" in message + # The Hub confirmed the check is an aws check, so nothing is left to verify. + assert "prowler_hub_get_check_details" not in message + + +async def test_a_check_from_another_provider_names_the_provider_that_has_it( + mcp_root_server, hub_router +): + """The ID exists; only the provider is wrong. Saying otherwise sends the + caller off to search for an ID they already hold.""" + hub_router.add("GET", github_check("azure"), status=404) + hub_router.add("GET", HUB_CHECK, json={"id": CHECK_ID, "provider": "aws"}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_code", + {"provider_id": "azure", "check_id": CHECK_ID}, + ) + + assert result.isError is True + message = result.content[0].text + assert "provider_id='aws'" in message + assert "No check with the ID" not in message + + +async def test_a_fixer_from_another_provider_is_not_reported_as_a_missing_fixer( + mcp_root_server, hub_router +): + """'That check has no fixer' about a check the provider never had is a lie + the caller cannot act on.""" + hub_router.add("GET", github_check("azure", "_fixer.py"), status=404) + hub_router.add("GET", HUB_CHECK, json={"id": CHECK_ID, "provider": "aws"}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_fixer", + {"provider_id": "azure", "check_id": CHECK_ID}, + ) + + assert result.isError is True + message = result.content[0].text + assert "provider_id='aws'" in message + assert "auto-remediation" not in message + + +async def test_a_check_id_that_exists_nowhere_is_still_reported_as_unknown( + mcp_root_server, hub_router +): + """The Hub not having the ID either is the one case that does justify the + original message.""" + hub_router.add("GET", github_check("azure"), status=404) + hub_router.add("GET", HUB_CHECK, status=404) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_code", + {"provider_id": "azure", "check_id": CHECK_ID}, + ) + + assert result.isError is True + assert "No check with the ID" in result.content[0].text + + +async def test_an_unreachable_hub_leaves_the_cause_open_rather_than_guessing( + mcp_root_server, hub_router +): + """With nothing to distinguish the causes, naming one of them is a guess.""" + hub_router.add("GET", github_check("azure"), status=404) + hub_router.add("GET", HUB_CHECK, status=503) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_code", + {"provider_id": "azure", "check_id": CHECK_ID}, + ) + + assert result.isError is True + message = result.content[0].text + assert "No check with the ID" not in message + assert "prowler_hub_get_check_details" in message + + +async def test_a_check_code_hit_never_asks_the_hub(mcp_root_server, hub_router): + """The Hub lookup exists to explain a 404. On the happy path it is dead + weight -- a second round trip for every call that already succeeded.""" + hub_router.add("GET", GITHUB_CHECK, text="class s3_bucket_public_access: ...") + + async with Client(mcp_root_server) as client: + result = await client.call_tool( + "prowler_hub_get_check_code", + {"provider_id": "aws", "check_id": CHECK_ID}, + ) + + assert "class s3_bucket_public_access" in result.data["content"] + assert hub_router.paths() == [f"GET {GITHUB_CHECK}"] + + +async def test_a_hub_outage_is_reported_rather_than_returned_as_an_empty_list( + mcp_root_server, hub_router +): + """An empty result set and a failed request are different answers.""" + hub_router.add("GET", CHECKS, status=500, json={"detail": "boom"}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp("prowler_hub_list_checks", {}) + + assert result.isError is True + assert result.structuredContent is None + + +@pytest.mark.parametrize( + ("check_id", "routed_as", "sent_as"), + [ + ("../../evil", f"{CHECKS}/../../evil", b"/api/check/..%2F..%2Fevil"), + ("s3/../evil", f"{CHECKS}/s3/../evil", b"/api/check/s3%2F..%2Fevil"), + ("..", f"{CHECKS}/..", b"/api/check/%2E%2E"), + ( + "s3_x?fields=all", + f"{CHECKS}/s3_x?fields=all", + b"/api/check/s3_x%3Ffields%3Dall", + ), + ("s3_x#frag", f"{CHECKS}/s3_x#frag", b"/api/check/s3_x%23frag"), + ], + ids=["traversal", "mid-path", "dot-segment", "query", "fragment"], +) +async def test_an_id_names_a_check_and_cannot_name_an_endpoint( + mcp_root_server, hub_router, check_id, routed_as, sent_as +): + """The bug this pins: httpx resolved "../.." away and the request left + /api/check for another endpoint of the Hub.""" + hub_router.add("GET", routed_as, status=404) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_details", {"check_id": check_id} + ) + + assert hub_router.requests[0].url.raw_path == sent_as + assert result.isError is True + assert "No check with the ID" in result.content[0].text + + +async def test_a_compliance_id_cannot_name_an_endpoint_either( + mcp_root_server, hub_router +): + """Every Hub path is built by the same helper, so this holds without its own + guard.""" + hub_router.add("GET", f"{COMPLIANCE}/../../evil", status=404) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_compliance_details", {"compliance_id": "../../evil"} + ) + + assert hub_router.requests[0].url.raw_path == b"/api/compliance/..%2F..%2Fevil" + assert result.isError is True + assert "No compliance framework with the ID" in result.content[0].text + + +async def test_a_check_source_url_confines_the_provider_and_the_check_alike( + mcp_root_server, hub_router +): + """Both halves of the GitHub raw URL come from the caller, so both are + confined.""" + hub_router.add("GET", github_check("../../../../evil"), status=404) + hub_router.add("GET", HUB_CHECK, json={"id": CHECK_ID, "provider": "aws"}) + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_code", + {"provider_id": "../../../../evil", "check_id": CHECK_ID}, + ) + + assert ( + hub_router.requests[0].url.raw_path + == github_check("..%2F..%2F..%2F..%2Fevil").encode() + ) + assert result.isError is True + + +async def test_a_hub_body_that_is_not_json_is_not_blamed_on_the_arguments( + mcp_root_server, hub_router +): + """An edge answering 200 with an HTML page decodes to the same + `JSONDecodeError` a malformed argument does, and the two mean opposite + things: nothing in this call can be corrected.""" + hub_router.add("GET", CHECKS, text="502 Bad Gateway") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp("prowler_hub_list_checks", {}) + + assert result.isError is True + message = result.content[0].text + assert "hub.prowler.com" in message + assert "could not read as JSON" in message + assert "Bad Gateway" not in message + assert "Send it as a real object" not in message + + +async def test_an_unreadable_hub_answer_does_not_become_an_unknown_check( + mcp_root_server, hub_router +): + """The 404 branch is the only one that may claim the ID does not exist. A + body that could not be read says nothing about the ID.""" + hub_router.add("GET", HUB_CHECK, text="not json") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_details", {"check_id": CHECK_ID} + ) + + assert result.isError is True + message = result.content[0].text + assert "could not read as JSON" in message + assert "No check with the ID" not in message + + +async def test_an_unreadable_hub_answer_leaves_a_missing_check_file_unexplained( + mcp_root_server, hub_router +): + """The Hub is asked which provider owns the check. A body it could not read + is no more of an answer than an outage, so it hedges the same way.""" + hub_router.add("GET", github_check("azure"), status=404) + hub_router.add("GET", HUB_CHECK, text="not json") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_hub_get_check_code", + {"provider_id": "azure", "check_id": CHECK_ID}, + ) + + assert result.isError is True + message = result.content[0].text + assert "No check with the ID" not in message + assert "prowler_hub_get_check_details" in message From 0715619435ef01c201f4f3458eb0d8e4448cbdc3 Mon Sep 17 00:00:00 2001 From: "Pablo Fernandez Guerra (PFE)" <148432447+pfe-nazaries@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:14:12 +0200 Subject: [PATCH 07/77] feat(ui): import Prowler OCSF findings from the Scans page (#12554) Co-authored-by: alejandrobailo --- .../msw/handlers/ingestions.fixtures.ts | 74 ++++ ui/__tests__/msw/handlers/ingestions.ts | 100 +++++ ui/actions/auth/auth.test.ts | 23 ++ ui/actions/auth/auth.ts | 1 + ui/app/(prowler)/scans/page.tsx | 4 + ui/app/(prowler)/scans/scans-page.harness.tsx | 323 ++++++++++++++++ .../scans/scans-page.integration.test.tsx | 326 +++++++++++++++++ .../ingestions/[ingestionId]/route.test.ts | 231 ++++++++++++ ui/app/api/ingestions/[ingestionId]/route.ts | 59 +++ ui/app/api/ingestions/route.test.ts | 345 ++++++++++++++++++ ui/app/api/ingestions/route.ts | 114 ++++++ ui/auth.config.test.ts | 3 + ui/auth.config.ts | 3 +- .../import-findings-drag-drop.added.md | 1 + ui/components/scans/import-findings-modal.tsx | 316 ++++++++++++++++ ui/components/scans/scans-page-shell.test.tsx | 84 ++++- ui/components/scans/scans-page-shell.tsx | 6 + ui/components/scans/use-ingestion-polling.ts | 157 ++++++++ .../file-upload/file-upload-dropzone.tsx | 48 ++- ui/hooks/use-auth.ts | 1 + ui/lib/ingestions.ts | 55 +++ ui/types/index.ts | 1 + ui/types/ingestions.ts | 21 ++ ui/types/users.ts | 72 ++-- 24 files changed, 2314 insertions(+), 54 deletions(-) create mode 100644 ui/__tests__/msw/handlers/ingestions.fixtures.ts create mode 100644 ui/__tests__/msw/handlers/ingestions.ts create mode 100644 ui/app/(prowler)/scans/scans-page.harness.tsx create mode 100644 ui/app/(prowler)/scans/scans-page.integration.test.tsx create mode 100644 ui/app/api/ingestions/[ingestionId]/route.test.ts create mode 100644 ui/app/api/ingestions/[ingestionId]/route.ts create mode 100644 ui/app/api/ingestions/route.test.ts create mode 100644 ui/app/api/ingestions/route.ts create mode 100644 ui/changelog.d/import-findings-drag-drop.added.md create mode 100644 ui/components/scans/import-findings-modal.tsx create mode 100644 ui/components/scans/use-ingestion-polling.ts create mode 100644 ui/lib/ingestions.ts create mode 100644 ui/types/ingestions.ts diff --git a/ui/__tests__/msw/handlers/ingestions.fixtures.ts b/ui/__tests__/msw/handlers/ingestions.fixtures.ts new file mode 100644 index 0000000000..25d7b16719 --- /dev/null +++ b/ui/__tests__/msw/handlers/ingestions.fixtures.ts @@ -0,0 +1,74 @@ +export const INGESTION_ID = "ingestion-123"; + +export interface IngestionFixture { + id: string; + totalRecords: number; + processedRecords: number; + invalidRecords: number; +} + +export const INGESTION_REJECTION = { + INVALID_REPORT: "invalid-report", + SUBSCRIPTION_REQUIRED: "subscription-required", + PERMISSION_DENIED: "permission-denied", + FILE_TOO_LARGE: "file-too-large", + RATE_LIMITED: "rate-limited", + UNEXPECTED: "unexpected", +} as const; + +export type IngestionRejection = + (typeof INGESTION_REJECTION)[keyof typeof INGESTION_REJECTION]; + +export interface IngestionRejectionFixture { + status: number; + message: string; +} + +export const ingestionRejectionFixture = ( + rejection: IngestionRejection, +): IngestionRejectionFixture => { + const fixtures = { + [INGESTION_REJECTION.INVALID_REPORT]: { + status: 400, + message: "The report is not a valid Prowler OCSF finding report.", + }, + [INGESTION_REJECTION.SUBSCRIPTION_REQUIRED]: { + status: 402, + message: "A Prowler Cloud subscription is required to import findings.", + }, + [INGESTION_REJECTION.PERMISSION_DENIED]: { + status: 403, + message: "You do not have permission to import findings.", + }, + [INGESTION_REJECTION.FILE_TOO_LARGE]: { + status: 413, + message: "The selected file exceeds the allowed upload size.", + }, + [INGESTION_REJECTION.RATE_LIMITED]: { + status: 429, + message: "Too many import requests. Please try again shortly.", + }, + [INGESTION_REJECTION.UNEXPECTED]: { + status: 500, + message: "Unable to start the import. Please try again.", + }, + } as const; + + return fixtures[rejection]; +}; + +export const ingestionFixture = (): IngestionFixture => ({ + id: INGESTION_ID, + totalRecords: 3, + processedRecords: 3, + invalidRecords: 1, +}); + +// Stopped partway: every record read is accounted for, so the unprocessed ones +// are reported as invalid. +export const partiallyProcessedIngestionFixture = (): IngestionFixture => ({ + id: INGESTION_ID, + totalRecords: 5, + processedRecords: 3, + invalidRecords: 2, +}); diff --git a/ui/__tests__/msw/handlers/ingestions.ts b/ui/__tests__/msw/handlers/ingestions.ts new file mode 100644 index 0000000000..45a61360e6 --- /dev/null +++ b/ui/__tests__/msw/handlers/ingestions.ts @@ -0,0 +1,100 @@ +import { delay, http, HttpResponse } from "msw"; + +import type { + IngestionFixture, + IngestionRejectionFixture, +} from "./ingestions.fixtures"; + +const API = "/api/ingestions"; + +// Counters stay zero until the job reaches a terminal status; `failed` still +// reports progress, which is what tells a partial import from one that landed nothing. +const ingestionResponse = ( + fixture: IngestionFixture, + status: "pending" | "processing" | "completed" | "failed", +) => { + const terminal = status === "completed" || status === "failed"; + return { + data: { + id: fixture.id, + status, + totalRecords: fixture.totalRecords, + processedRecords: terminal ? fixture.processedRecords : 0, + invalidRecords: terminal ? fixture.invalidRecords : 0, + }, + }; +}; + +interface IngestionHandlerOptions { + uploadRejection?: IngestionRejectionFixture; + uploadDelayMs?: number; + statusErrorAt?: number; + statusDelayMs?: number; + statusResponseGate?: Promise; + statusSequence?: Array<"processing" | "completed" | "failed">; + onStatusRequest?: (inFlight: number) => void; +} + +export const handlersForIngestion = ( + fixture: IngestionFixture, + { + uploadRejection, + uploadDelayMs, + statusErrorAt, + statusDelayMs, + statusResponseGate, + statusSequence, + onStatusRequest, + }: IngestionHandlerOptions = {}, +) => { + let statusRequestCount = 0; + let inFlightStatusRequests = 0; + + return [ + http.post(API, async ({ request }) => { + const formData = await request.formData(); + if (uploadDelayMs) await delay(uploadDelayMs); + if (!(formData.get("file") instanceof File)) { + return HttpResponse.json( + { error: "A file is required." }, + { status: 400 }, + ); + } + + if (uploadRejection) { + return HttpResponse.json( + { error: uploadRejection.message }, + { status: uploadRejection.status }, + ); + } + + return HttpResponse.json(ingestionResponse(fixture, "pending"), { + status: 202, + }); + }), + http.get(`${API}/:id`, async ({ params }) => { + if (params.id !== fixture.id) { + return HttpResponse.json({ error: "Not found." }, { status: 404 }); + } + + statusRequestCount += 1; + inFlightStatusRequests += 1; + onStatusRequest?.(inFlightStatusRequests); + if (statusDelayMs) await delay(statusDelayMs); + if (statusResponseGate) await statusResponseGate; + inFlightStatusRequests -= 1; + onStatusRequest?.(inFlightStatusRequests); + if (statusRequestCount === statusErrorAt) { + return HttpResponse.json( + { error: "Unable to retrieve the import status. Please try again." }, + { status: 503 }, + ); + } + + const status = + statusSequence?.[statusRequestCount - 1] ?? + (statusRequestCount === 1 ? "processing" : "completed"); + return HttpResponse.json(ingestionResponse(fixture, status)); + }), + ]; +}; diff --git a/ui/actions/auth/auth.test.ts b/ui/actions/auth/auth.test.ts index 016747b065..1f20392bb8 100644 --- a/ui/actions/auth/auth.test.ts +++ b/ui/actions/auth/auth.test.ts @@ -132,6 +132,29 @@ describe("auth actions", () => { expect(requestUrl.searchParams.get("utm_source")).toBe("blackhat"); }); + it("should carry manage_ingestions into the session permissions", async () => { + // Given + mockUserMe({ manage_ingestions: true }); + + // When + const result = await getUserByMe("access-token"); + + // Then + expect(result.permissions.manage_ingestions).toBe(true); + }); + + it("should default manage_ingestions to false when the role omits it", async () => { + // Given + mockUserMe({ manage_scans: true }); + + // When + const result = await getUserByMe("access-token"); + + // Then + expect(result.permissions.manage_ingestions).toBe(false); + expect(result.permissions.manage_scans).toBe(true); + }); + it("should carry manage_lighthouse_ai_configuration into the session permissions", async () => { // Given mockUserMe({ manage_lighthouse_ai_configuration: true }); diff --git a/ui/actions/auth/auth.ts b/ui/actions/auth/auth.ts index 0df5fe81c9..6d275bbf92 100644 --- a/ui/actions/auth/auth.ts +++ b/ui/actions/auth/auth.ts @@ -180,6 +180,7 @@ export const getUserByMe = async ( manage_account: userRole.attributes.manage_account || false, manage_providers: userRole.attributes.manage_providers || false, manage_scans: userRole.attributes.manage_scans || false, + manage_ingestions: userRole.attributes.manage_ingestions || false, manage_integrations: userRole.attributes.manage_integrations || false, manage_billing: userRole.attributes.manage_billing || false, manage_alerts: userRole.attributes.manage_alerts || false, diff --git a/ui/app/(prowler)/scans/page.tsx b/ui/app/(prowler)/scans/page.tsx index a8330f64aa..4b308921e4 100644 --- a/ui/app/(prowler)/scans/page.tsx +++ b/ui/app/(prowler)/scans/page.tsx @@ -193,6 +193,9 @@ export default async function Scans({ const hasManageScansPermission = Boolean( session?.user?.permissions?.manage_scans, ); + const hasManageIngestionsPermission = Boolean( + session?.user?.permissions?.manage_ingestions, + ); const activeScanCount = await getActiveScanCount(resolvedSearchParams); // Mirrors ScansPageShell's launch gate: it only mounts the view-first-scan trigger // when Launch Scan is usable (manage_scans + a connected provider). Without the @@ -218,6 +221,7 @@ export default async function Scans({ providers={providers} providerGroups={providerGroups} hasManageScansPermission={hasManageScansPermission} + hasManageIngestionsPermission={hasManageIngestionsPermission} activeScanCount={activeScanCount} > ; +} + +export class ScansPageHarness extends BrowserHarness { + private maxInFlightStatusRequests = 0; + private mounted: ReturnType | null = null; + private releaseHeldStatusResponse: (() => void) | null = null; + private statusDelayMs = 0; + + async mount({ + hasManageIngestionsPermission = true, + hasManageScansPermission = false, + holdStatusResponse = false, + uploadRejection, + uploadDelayMs, + statusErrorAt, + statusDelayMs, + statusSequence, + }: MountOptions = {}): Promise { + const statusResponseGate = holdStatusResponse + ? new Promise((resolve) => { + this.releaseHeldStatusResponse = resolve; + }) + : undefined; + + worker.use( + ...handlersForIngestion(this.fixture, { + uploadRejection, + uploadDelayMs, + statusErrorAt, + statusDelayMs, + statusResponseGate, + statusSequence, + onStatusRequest: (inFlight) => { + this.maxInFlightStatusRequests = Math.max( + this.maxInFlightStatusRequests, + inFlight, + ); + }, + }), + ); + this.trackRequests(worker); + this.statusDelayMs = statusDelayMs ?? 0; + + this.mounted = render( + + + , + ); + } + + async leaveScansPage(): Promise { + const mounted = await this.mounted; + if (!mounted) throw new Error("leaveScansPage: the page is not mounted"); + mounted.unmount(); + this.mounted = null; + } + + hasImportFindingsAction(): boolean { + return this.buttonByText(/Import Findings/) !== null; + } + + async openImportFindings(): Promise { + await this.clickButton(/Import Findings/); + await this.waitForText(/Import findings/i); + } + + async selectFile(file: File): Promise { + const input = await this.waitFor(() => + this.container.querySelector('input[type="file"]'), + ); + await this.user.upload(input, file); + } + + async dropFile(file: File): Promise { + await this.attemptDrop(file); + await this.waitFor(() => + this.q('[data-testid="import-findings-dropzone"]')?.textContent?.includes( + file.name, + ), + ); + } + + /** Drop without waiting for the file to be taken: dropFile hangs on a refused drop. */ + async attemptDrop(file: File): Promise { + const dropzone = await this.waitFor(() => + this.q('[data-testid="import-findings-dropzone"] [role="button"]'), + ); + const dataTransfer = new DataTransfer(); + dataTransfer.items.add(file); + dropzone.dispatchEvent( + new DragEvent("drop", { bubbles: true, dataTransfer }), + ); + } + + /** Both halves matter: drop and keyboard gate on the zone, the file picker on the input. */ + isDropzoneFrozen(): boolean { + const zone = this.q( + '[data-testid="import-findings-dropzone"] [role="button"]', + ); + const input = this.container.querySelector( + '[data-testid="import-findings-dropzone"] input[type="file"]', + ); + return ( + zone?.getAttribute("aria-disabled") === "true" && input?.disabled === true + ); + } + + async activateDropzoneWithKeyboard(): Promise { + const dropzone = await this.waitFor(() => + this.q('[data-testid="import-findings-dropzone"] [role="button"]'), + ); + const input = await this.waitFor(() => + this.container.querySelector('input[type="file"]'), + ); + let opened = false; + input.addEventListener("click", () => { + opened = true; + }); + + dropzone.focus(); + await this.user.keyboard("[Enter]"); + return opened; + } + + isImportEnabled(): boolean { + return !this.buttonByText(/Start import/i)?.disabled; + } + + async waitForValidationMessage(message: RegExp): Promise { + await this.waitForText(message); + } + + async waitForUploadError(message: RegExp): Promise { + await this.waitForText(message); + } + + async waitForUploadInProgress(): Promise { + await this.waitFor( + () => this.buttonByText(/Importing/i), + 5000, + "the upload to report progress", + ); + } + + isUploadInProgress(): boolean { + const submit = this.buttonByText(/Importing/i); + return submit !== null && submit.disabled; + } + + async closeImportFindings(): Promise { + await this.user.keyboard("[Escape]"); + await this.waitFor(() => + this.q('[role="dialog"]') === null ? true : null, + ); + } + + async closeImmediatelyBeforeStatusCompletes(): Promise { + const closeButton = await this.waitForButton(/^Close$/i); + const releaseStatusResponse = this.releaseHeldStatusResponse; + if (!releaseStatusResponse) { + throw new Error( + "closeImmediatelyBeforeStatusCompletes: no status response is held", + ); + } + + closeButton.click(); + releaseStatusResponse(); + this.releaseHeldStatusResponse = null; + await this.waitFor(() => + this.q('[role="dialog"]') === null ? true : null, + ); + } + + selectedFileName(): string | null { + const dropzone = this.q('[data-testid="import-findings-dropzone"]'); + return dropzone?.textContent?.match(/[^\s]+\.json/i)?.[0] ?? null; + } + + async submitImport(): Promise { + await this.clickButton(/Start import/i); + } + + async retryUpload(): Promise { + await this.clickButton(/Retry import/i); + await this.waitFor(() => (this.ingestionPostCount === 2 ? true : null)); + } + + /** Anchored on "Import completed": the failed summary reports the same counters. */ + async waitForCompletedSummary(): Promise { + const { processedRecords, totalRecords, invalidRecords } = this.fixture; + await this.waitForText( + new RegExp( + `Import completed: ${totalRecords} total records, ${processedRecords} processed, ${invalidRecords} invalid`, + "i", + ), + 15000, + ); + } + + hasCompletionNotification(): boolean { + return this.containsText(/Findings import completed/i); + } + + hasCompletedSummary(): boolean { + return this.containsText(/Import completed:/i); + } + + hasStopTrackingAction(): boolean { + return this.buttonByText(/Stop tracking/i) !== null; + } + + async waitForCompletionNotification(): Promise { + await this.waitFor( + () => this.hasCompletionNotification(), + 15000, + "the import completion notification", + ); + } + + async waitForTrackingStatus(): Promise { + await this.waitForText(/Import is processing/i); + } + + async waitForStatusError(): Promise { + await this.waitForText(/Unable to retrieve the import status/i, 15000); + } + + async waitForFailedImport(): Promise { + await this.waitForText(/Import failed/i, 15000); + } + + async waitForFailedImportSummary(): Promise { + const { processedRecords, totalRecords, invalidRecords } = this.fixture; + await this.waitForText( + new RegExp( + `${processedRecords} of ${totalRecords} records processed, ${invalidRecords} invalid`, + "i", + ), + 15000, + ); + } + + async retryStatus(): Promise { + await this.clickButton(/Retry status/i); + await this.waitFor(() => + this.ingestionStatusPollCount >= 2 ? true : null, + ); + } + + async waitForFirstStatusPoll(): Promise { + await this.waitFor( + () => this.ingestionStatusPollCount >= 1, + 5000, + "the first status poll", + ); + } + + /** Outlast an uncancelled poll: its response lands, then the modal's 5s interval passes and the next would fire. */ + async waitPastTheNextPoll(): Promise { + await this.waitForTransition(this.statusDelayMs + 5700); + } + + get ingestionPostCount(): number { + return this.countRequests("POST", "/api/ingestions"); + } + + get ingestionStatusPollCount(): number { + return this.countRequests("GET", "/api/ingestions/"); + } + + get maximumInFlightStatusRequests(): number { + return this.maxInFlightStatusRequests; + } + + /** A page refresh is the only thing that brings an imported scan into the table. */ + get pageRefreshCount(): number { + return vi.mocked(readMockedRouter().refresh).mock.calls.length; + } + + async uploadedFileName(): Promise { + const entry = [...this.requestLog] + .reverse() + .find( + (request) => + request.method === "POST" && + new URL(request.url).pathname === "/api/ingestions", + ); + if (!entry) return null; + + const file = (await entry.request.formData()).get("file"); + return file instanceof File ? file.name : null; + } +} diff --git a/ui/app/(prowler)/scans/scans-page.integration.test.tsx b/ui/app/(prowler)/scans/scans-page.integration.test.tsx new file mode 100644 index 0000000000..d150a2d0f8 --- /dev/null +++ b/ui/app/(prowler)/scans/scans-page.integration.test.tsx @@ -0,0 +1,326 @@ +import { describe, expect } from "vitest"; + +import { it } from "@/__tests__/fixtures"; +import { + INGESTION_REJECTION, + ingestionFixture, + ingestionRejectionFixture, + partiallyProcessedIngestionFixture, +} from "@/__tests__/msw/handlers/ingestions.fixtures"; + +import { ScansPageHarness } from "./scans-page.harness"; + +describe("Scans page import findings", () => { + it("imports one valid finding file without scan permission or providers", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount(); + + expect(harness.hasImportFindingsAction()).toBe(true); + await harness.openImportFindings(); + await harness.selectFile( + new File(['[{"type":"finding"}]'], "findings.ocsf.json", { + type: "application/json", + }), + ); + await harness.submitImport(); + + await harness.waitForCompletedSummary(); + // The summary is on screen, so the toast would have been raised in the same + // render: its absence is the open dialog suppressing it. + expect(harness.hasCompletionNotification()).toBe(false); + expect(harness.pageRefreshCount).toBe(1); + expect(harness.ingestionPostCount).toBe(1); + expect(await harness.uploadedFileName()).toBe("findings.ocsf.json"); + expect(harness.ingestionStatusPollCount).toBeGreaterThanOrEqual(2); + }); + + it("hides Import Findings in Local Server", async ({ seedRuntimeConfig }) => { + seedRuntimeConfig({ cloudEnabled: false }); + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount(); + + expect(harness.hasImportFindingsAction()).toBe(false); + }); + + it("hides Import Findings without Manage Ingestions", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ hasManageIngestionsPermission: false }); + + expect(harness.hasImportFindingsAction()).toBe(false); + }); + + it("supports keyboard activation and drag-and-drop selection", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount(); + await harness.openImportFindings(); + + await expect(harness.activateDropzoneWithKeyboard()).resolves.toBe(true); + await harness.dropFile( + new File(["[]"], "dropped.OCSF.JSON", { type: "application/json" }), + ); + + expect(harness.selectedFileName()).toBe("dropped.OCSF.JSON"); + expect(harness.isImportEnabled()).toBe(true); + }); + + it("replaces a selected file and rejects unsupported and empty selections", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount(); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "first.ocsf.json")); + await harness.selectFile(new File(["[]"], "replacement.ocsf.json")); + + expect(harness.selectedFileName()).toBe("replacement.ocsf.json"); + await harness.selectFile(new File(["[]"], "unsupported.json")); + await harness.waitForValidationMessage(/\.ocsf\.json/i); + expect(harness.ingestionPostCount).toBe(0); + + await harness.selectFile(new File([], "empty.ocsf.json")); + await harness.waitForValidationMessage(/empty/i); + expect(harness.ingestionPostCount).toBe(0); + }); + + it("clears an unsubmitted selection after closing the dialog", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount(); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.closeImportFindings(); + await harness.openImportFindings(); + + expect(harness.selectedFileName()).toBeNull(); + expect(harness.isImportEnabled()).toBe(false); + }); + + for (const rejection of Object.values(INGESTION_REJECTION)) { + it(`keeps the file recoverable after a ${rejection} upload rejection`, async () => { + const rejectionFixture = ingestionRejectionFixture(rejection); + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ uploadRejection: rejectionFixture }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + + await harness.waitForUploadError( + new RegExp(rejectionFixture.message, "i"), + ); + expect(harness.selectedFileName()).toBe("findings.ocsf.json"); + expect(harness.ingestionPostCount).toBe(1); + + await harness.retryUpload(); + expect(harness.ingestionPostCount).toBe(2); + }); + } + + it("continues tracking an accepted import while the dialog is closed", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusSequence: ["processing", "completed"] }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForTrackingStatus(); + await harness.closeImportFindings(); + + await harness.openImportFindings(); + await harness.waitForCompletedSummary(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("keeps an in-flight submission after closing and reopening the dialog", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ + uploadDelayMs: 3000, + statusSequence: ["processing", "completed"], + }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForUploadInProgress(); + await harness.closeImportFindings(); + await harness.openImportFindings(); + + expect(harness.isUploadInProgress()).toBe(true); + expect(harness.selectedFileName()).toBe("findings.ocsf.json"); + + await harness.waitForTrackingStatus(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("refuses to swap the file while an import is in flight", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ + uploadDelayMs: 3000, + statusSequence: ["processing", "completed"], + }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForUploadInProgress(); + + expect(harness.isDropzoneFrozen()).toBe(true); + await harness.attemptDrop(new File(["[]"], "swapped.ocsf.json")); + await expect(harness.activateDropzoneWithKeyboard()).resolves.toBe(false); + + expect(harness.selectedFileName()).toBe("findings.ocsf.json"); + // A swap would reset to ready, re-enabling submission for a second POST. + expect(harness.isUploadInProgress()).toBe(true); + + await harness.waitForTrackingStatus(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("notifies when an import completes while the dialog is closed", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusSequence: ["processing", "completed"] }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForTrackingStatus(); + await harness.closeImportFindings(); + + await harness.waitForCompletionNotification(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("offers a fresh import when reopening after a background completion", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusSequence: ["processing", "completed"] }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForTrackingStatus(); + await harness.closeImportFindings(); + await harness.waitForCompletionNotification(); + + await harness.openImportFindings(); + // Without the reopen reset the summary renders in place of the dropzone and + // the submit, leaving no way to import a second report. + expect(harness.hasCompletedSummary()).toBe(false); + await harness.selectFile(new File(["[]"], "another.ocsf.json")); + expect(harness.selectedFileName()).toBe("another.ocsf.json"); + expect(harness.isImportEnabled()).toBe(true); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("notifies when the dialog closes immediately before the import completes", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ + holdStatusResponse: true, + statusSequence: ["completed"], + }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForFirstStatusPoll(); + + await harness.closeImmediatelyBeforeStatusCompletes(); + + await harness.waitForCompletionNotification(); + expect(harness.pageRefreshCount).toBe(1); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("retries a failed terminal import with the selected file", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusSequence: ["failed"] }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForFailedImport(); + expect(harness.pageRefreshCount).toBe(0); + + await harness.retryUpload(); + expect(harness.ingestionPostCount).toBe(2); + }); + + it("reports how many records a failed import processed", async () => { + const harness = new ScansPageHarness(partiallyProcessedIngestionFixture()); + await harness.mount({ statusSequence: ["failed"] }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + + await harness.waitForFailedImport(); + await harness.waitForFailedImportSummary(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("clears a terminal result after closing the dialog", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusSequence: ["failed"] }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForFailedImport(); + await harness.closeImportFindings(); + await harness.openImportFindings(); + + expect(harness.selectedFileName()).toBeNull(); + expect(harness.isImportEnabled()).toBe(false); + }); + + it("retries a transient status failure without re-uploading", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ + statusErrorAt: 1, + statusSequence: ["processing", "completed"], + }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForStatusError(); + + await harness.retryStatus(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("holds a stuck import instead of freeing a second upload", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusErrorAt: 1 }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForStatusError(); + + // The ingestion API has no cancellation and every POST opens a new job, so + // letting go of an accepted one would only duplicate it. + expect(harness.hasStopTrackingAction()).toBe(false); + expect(harness.isDropzoneFrozen()).toBe(true); + expect(harness.isImportEnabled()).toBe(false); + + await harness.retryStatus(); + expect(harness.ingestionPostCount).toBe(1); + }); + + it("never overlaps status polls for an accepted import", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + // The delay has to outlast POLL_INTERVAL_MS: an interval-driven poll fires + // its second request while this first one is still in flight. + await harness.mount({ + statusDelayMs: 7500, + statusSequence: ["completed"], + }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + + await harness.waitForCompletedSummary(); + expect(harness.maximumInFlightStatusRequests).toBe(1); + }); + + it("stops polling a tracked import after leaving the page", async () => { + const harness = new ScansPageHarness(ingestionFixture()); + await harness.mount({ statusDelayMs: 500 }); + await harness.openImportFindings(); + await harness.selectFile(new File(["[]"], "findings.ocsf.json")); + await harness.submitImport(); + await harness.waitForFirstStatusPoll(); + await harness.leaveScansPage(); + const pollsWhenLeaving = harness.ingestionStatusPollCount; + + // An unaborted poll answers into the dead page and chains the next one, + // refreshing and toasting over whatever route the user moved to. + await harness.waitPastTheNextPoll(); + expect(harness.ingestionStatusPollCount).toBe(pollsWhenLeaving); + }); +}); diff --git a/ui/app/api/ingestions/[ingestionId]/route.test.ts b/ui/app/api/ingestions/[ingestionId]/route.test.ts new file mode 100644 index 0000000000..f0723192d1 --- /dev/null +++ b/ui/app/api/ingestions/[ingestionId]/route.test.ts @@ -0,0 +1,231 @@ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; + +import { GET } from "./route"; + +const { getAuthHeadersMock, isCloudMock } = vi.hoisted(() => ({ + getAuthHeadersMock: vi.fn(), + isCloudMock: vi.fn(), +})); + +vi.mock("@/lib", () => ({ + apiBaseUrl: "https://api.example.com/api/v1", + getAuthHeaders: getAuthHeadersMock, +})); + +vi.mock("@/lib/shared/env", () => ({ + isCloud: isCloudMock, +})); + +describe("GET /api/ingestions/[ingestionId]", () => { + const server = setupServer(); + + beforeAll(() => server.listen({ onUnhandledRequest: "error" })); + + afterEach(() => { + server.resetHandlers(); + vi.unstubAllGlobals(); + vi.clearAllMocks(); + }); + + afterAll(() => server.close()); + + it("returns not found in OSS and Local Server before reading the ingestion identifier", async () => { + isCloudMock.mockReturnValue(false); + const fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + expect(response.status).toBe(404); + expect(getAuthHeadersMock).not.toHaveBeenCalled(); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + it("forwards a Cloud status request and translates its typed response", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.get("https://api.example.com/api/v1/ingestions/ingestion-123", () => + HttpResponse.json({ + data: { + id: "ingestion-123", + type: "ingestions", + attributes: { + status: "processing", + summary: { total: 5, processed: 3, invalid: 1 }, + requested_at: "2026-08-26T11:23:20.265770Z", + started_at: "2026-08-26T11:23:20.372762Z", + completed_at: null, + }, + }, + }), + ), + ); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + await expect(response.json()).resolves.toEqual({ + data: { + id: "ingestion-123", + status: "processing", + totalRecords: 5, + processedRecords: 3, + invalidRecords: 1, + }, + }); + }); + + it("forwards an identifier that needs escaping as one encoded path segment", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + let requestedUrl = ""; + server.use( + http.get("https://api.example.com/api/v1/ingestions/*", ({ request }) => { + requestedUrl = request.url; + return HttpResponse.json({ + data: { id: "2026/08 report", attributes: { status: "pending" } }, + }); + }), + ); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "2026/08 report" }), + }); + + expect(requestedUrl).toBe( + "https://api.example.com/api/v1/ingestions/2026%2F08%20report", + ); + expect(response.status).toBe(200); + }); + + it("sanitizes unreadable upstream status failures", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.get( + "https://api.example.com/api/v1/ingestions/ingestion-123", + () => + new HttpResponse("upstream details", { + status: 503, + headers: { "content-type": "text/html" }, + }), + ), + ); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + expect(response.status).toBe(503); + await expect(response.json()).resolves.toEqual({ + error: "Unable to retrieve the import status. Please try again.", + }); + }); + + it("returns a safe bad gateway response when the ingestion API connection fails", async () => { + // Given + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + vi.stubGlobal( + "fetch", + vi.fn().mockRejectedValue(new Error("socket hang up from api.internal")), + ); + + // When + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + // Then + expect(response.status).toBe(502); + await expect(response.json()).resolves.toEqual({ + error: "Unable to retrieve the import status. Please try again.", + }); + }); + + it("does not expose structured upstream status failures", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.get("https://api.example.com/api/v1/ingestions/ingestion-123", () => + HttpResponse.json( + { errors: [{ code: "internal_error", detail: "upstream details" }] }, + { status: 503 }, + ), + ), + ); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + expect(response.status).toBe(503); + await expect(response.json()).resolves.toEqual({ + error: "Unable to retrieve the import status. Please try again.", + }); + }); + + it("tracks a status response that has not reported its summary yet", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.get("https://api.example.com/api/v1/ingestions/ingestion-123", () => + HttpResponse.json({ + data: { + type: "ingestions", + id: "ingestion-123", + attributes: { status: "pending" }, + }, + }), + ), + ); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + expect(response.status).toBe(200); + await expect(response.json()).resolves.toEqual({ + data: { + id: "ingestion-123", + status: "pending", + totalRecords: 0, + processedRecords: 0, + invalidRecords: 0, + }, + }); + }); + + it("rejects malformed accepted status responses", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.get("https://api.example.com/api/v1/ingestions/ingestion-123", () => + HttpResponse.json({ data: { id: "ingestion-123", attributes: {} } }), + ), + ); + + const response = await GET(new Request("http://localhost/api/ingestions"), { + params: Promise.resolve({ ingestionId: "ingestion-123" }), + }); + + expect(response.status).toBe(502); + await expect(response.json()).resolves.toEqual({ + error: "Unable to retrieve the import status. Please try again.", + }); + }); +}); diff --git a/ui/app/api/ingestions/[ingestionId]/route.ts b/ui/app/api/ingestions/[ingestionId]/route.ts new file mode 100644 index 0000000000..aa4555c657 --- /dev/null +++ b/ui/app/api/ingestions/[ingestionId]/route.ts @@ -0,0 +1,59 @@ +import { NextResponse } from "next/server"; + +import { apiBaseUrl, getAuthHeaders } from "@/lib"; +import { parseIngestion } from "@/lib/ingestions"; +import { isCloud } from "@/lib/shared/env"; + +export const dynamic = "force-dynamic"; +export const runtime = "nodejs"; + +interface IngestionRouteContext { + params: Promise<{ + ingestionId: string; + }>; +} + +const INVALID_INGESTION_RESPONSE = + "Unable to retrieve the import status. Please try again."; + +export async function GET( + _request: Request, + { params }: IngestionRouteContext, +) { + if (!isCloud()) return new Response(null, { status: 404 }); + + const { ingestionId } = await params; + if (!ingestionId) return new Response(null, { status: 404 }); + + const headers = await getAuthHeaders({ contentType: false }); + let upstreamResponse: Response; + try { + upstreamResponse = await fetch( + `${apiBaseUrl}/ingestions/${encodeURIComponent(ingestionId)}`, + { headers, cache: "no-store" }, + ); + } catch { + return NextResponse.json( + { error: INVALID_INGESTION_RESPONSE }, + { status: 502 }, + ); + } + const payload = await upstreamResponse.json().catch(() => undefined); + + if (!upstreamResponse.ok) { + return NextResponse.json( + { error: INVALID_INGESTION_RESPONSE }, + { status: upstreamResponse.status }, + ); + } + + const ingestion = parseIngestion(payload); + if (!ingestion) { + return NextResponse.json( + { error: INVALID_INGESTION_RESPONSE }, + { status: 502 }, + ); + } + + return NextResponse.json({ data: ingestion }); +} diff --git a/ui/app/api/ingestions/route.test.ts b/ui/app/api/ingestions/route.test.ts new file mode 100644 index 0000000000..3142c1375b --- /dev/null +++ b/ui/app/api/ingestions/route.test.ts @@ -0,0 +1,345 @@ +import { http, HttpResponse } from "msw"; +import { setupServer } from "msw/node"; +import { + afterAll, + afterEach, + beforeAll, + describe, + expect, + it, + vi, +} from "vitest"; + +import { POST } from "./route"; + +// Browser MSW intercepts the same-origin request before Next can run this +// Route Handler, so these tests call POST directly. +const { getAuthHeadersMock, isCloudMock } = vi.hoisted(() => ({ + getAuthHeadersMock: vi.fn(), + isCloudMock: vi.fn(), +})); + +vi.mock("@/lib", () => ({ + apiBaseUrl: "https://api.example.com/api/v1", + getAuthHeaders: getAuthHeadersMock, +})); + +vi.mock("@/lib/shared/env", () => ({ + isCloud: isCloudMock, +})); + +// A browser upload always reaches the route with a length on the wire, and the +// route refuses anything it cannot measure, so a forwarded Request needs one. +const uploadRequest = (body = "report") => + new Request("http://localhost/api/ingestions", { + method: "POST", + headers: { + "content-length": String(new TextEncoder().encode(body).length), + }, + body, + }); + +describe("POST /api/ingestions", () => { + const server = setupServer(); + + beforeAll(() => server.listen({ onUnhandledRequest: "error" })); + + afterEach(() => { + server.resetHandlers(); + vi.unstubAllGlobals(); + vi.clearAllMocks(); + }); + + afterAll(() => server.close()); + + it("returns not found in OSS and Local Server without authenticating or forwarding the upload", async () => { + isCloudMock.mockReturnValue(false); + const fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock); + const request = new Request("http://localhost/api/ingestions", { + method: "POST", + headers: { "content-type": "multipart/form-data; boundary=report" }, + body: "--report--", + }); + + const response = await POST(request); + + expect(response.status).toBe(404); + expect(request.body?.locked).toBe(false); + expect(getAuthHeadersMock).not.toHaveBeenCalled(); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + it("forwards the original multipart stream and boundary in Cloud", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + let contentType: string | null = null; + let contentLength: string | null = null; + let uploadedBody = ""; + server.use( + http.post( + "https://api.example.com/api/v1/ingestions", + async ({ request }) => { + contentType = request.headers.get("content-type"); + contentLength = request.headers.get("content-length"); + uploadedBody = await request.text(); + return HttpResponse.json({ + data: { + id: "ingestion-123", + type: "ingestions", + attributes: { + status: "pending", + summary: { total: 0, processed: 0, invalid: 0 }, + requested_at: "2026-08-26T11:23:20.265770Z", + started_at: null, + completed_at: null, + }, + }, + }); + }, + ), + ); + // Built by hand: a Request created from FormData carries no content-length + // header, which is what this test pins. + const boundary = "----ingestionBoundary"; + const multipartBody = [ + `--${boundary}`, + 'Content-Disposition: form-data; name="file"; filename="findings.ocsf.json"', + "Content-Type: application/json", + "", + "finding report", + `--${boundary}--`, + "", + ].join("\r\n"); + const request = new Request("http://localhost/api/ingestions", { + method: "POST", + headers: { + "content-type": `multipart/form-data; boundary=${boundary}`, + "content-length": String( + new TextEncoder().encode(multipartBody).length, + ), + }, + body: multipartBody, + }); + + const response = await POST(request); + + expect(contentType).toBe(`multipart/form-data; boundary=${boundary}`); + expect(contentLength).toBe( + String(new TextEncoder().encode(multipartBody).length), + ); + expect(uploadedBody).toBe(multipartBody); + await expect(response.json()).resolves.toEqual({ + data: { + id: "ingestion-123", + status: "pending", + totalRecords: 0, + processedRecords: 0, + invalidRecords: 0, + }, + }); + }); + + it("refuses an upload it cannot measure instead of forwarding it chunked", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + const fetchMock = vi.fn(); + vi.stubGlobal("fetch", fetchMock); + // A Request built from FormData carries no content-length, and the ingestion + // API parses no file out of the chunked body that would be forwarded. + const request = new Request("http://localhost/api/ingestions", { + method: "POST", + headers: { "content-type": "multipart/form-data; boundary=report" }, + body: "--report--", + }); + + const response = await POST(request); + + expect(response.status).toBe(411); + expect(fetchMock).not.toHaveBeenCalled(); + expect(request.body?.locked).toBe(false); + await expect(response.json()).resolves.toEqual({ + error: "Unable to start the import. Please try again.", + }); + }); + + it("sanitizes unexpected upstream error pages", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.post( + "https://api.example.com/api/v1/ingestions", + () => + new HttpResponse("upstream details", { + status: 502, + headers: { "content-type": "text/html" }, + }), + ), + ); + + const response = await POST(uploadRequest()); + + expect(response.status).toBe(502); + await expect(response.json()).resolves.toEqual({ + error: "Unable to start the import. Please try again.", + }); + }); + + it("returns a safe bad gateway response when the ingestion API connection fails", async () => { + // Given + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + vi.stubGlobal( + "fetch", + vi.fn().mockRejectedValue(new Error("connect ECONNREFUSED api.internal")), + ); + + // When + const response = await POST(uploadRequest()); + + // Then + expect(response.status).toBe(502); + await expect(response.json()).resolves.toEqual({ + error: "Unable to start the import. Please try again.", + }); + }); + + it.each([ + [400, "invalid", "The report is not a valid Prowler OCSF finding report."], + [ + 402, + "subscription_required", + "A Prowler Cloud subscription is required to import findings.", + ], + [ + 403, + "permission_denied", + "You do not have permission to import findings.", + ], + [ + 413, + "file_too_large", + "The selected file exceeds the allowed upload size.", + ], + [ + 429, + "rate_limited", + "Too many import requests. Please try again shortly.", + ], + ])( + "maps known upstream rejection %i/%s to safe import guidance", + async (status, code, message) => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.post("https://api.example.com/api/v1/ingestions", () => + HttpResponse.json( + { errors: [{ code, detail: "internal implementation detail" }] }, + { status }, + ), + ), + ); + + const response = await POST(uploadRequest()); + + expect(response.status).toBe(status); + await expect(response.json()).resolves.toEqual({ error: message }); + }, + ); + + const STATUS_TIER_REJECTIONS = [ + [400, "The report is not a valid Prowler OCSF finding report."], + [402, "A Prowler Cloud subscription is required to import findings."], + [403, "You do not have permission to import findings."], + [413, "The selected file exceeds the allowed upload size."], + [429, "Too many import requests. Please try again shortly."], + ] as const; + + it.each(STATUS_TIER_REJECTIONS)( + "maps a codeless upstream rejection to the %i status guidance", + async (status, message) => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.post("https://api.example.com/api/v1/ingestions", () => + HttpResponse.json( + { detail: "internal implementation detail" }, + { status }, + ), + ), + ); + + const response = await POST(uploadRequest()); + + expect(response.status).toBe(status); + await expect(response.json()).resolves.toEqual({ error: message }); + }, + ); + + it.each(STATUS_TIER_REJECTIONS)( + "falls through an unrecognized error code to the %i status guidance", + async (status, message) => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.post("https://api.example.com/api/v1/ingestions", () => + HttpResponse.json( + { + errors: [ + { + code: "invalid_findings", + detail: "internal implementation detail", + }, + ], + }, + { status }, + ), + ), + ); + + const response = await POST(uploadRequest()); + + expect(response.status).toBe(status); + await expect(response.json()).resolves.toEqual({ error: message }); + }, + ); + + // An empty id parses into a trackable-looking job whose poll URL, + // `/api/ingestions/`, matches no route: a created import reads as a failure. + it.each([ + ["no job identifier", { attributes: { status: "pending" } }], + ["an empty job identifier", { id: "", attributes: { status: "pending" } }], + ])("refuses an accepted response with %s", async (_shape, data) => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.post("https://api.example.com/api/v1/ingestions", () => + HttpResponse.json({ data }), + ), + ); + + const response = await POST(uploadRequest()); + + expect(response.status).toBe(502); + await expect(response.json()).resolves.toEqual({ + error: "Unable to start the import. Please try again.", + }); + }); + + it("rejects accepted responses that cannot start a trackable ingestion", async () => { + isCloudMock.mockReturnValue(true); + getAuthHeadersMock.mockResolvedValue({ Authorization: "Bearer token" }); + server.use( + http.post("https://api.example.com/api/v1/ingestions", () => + HttpResponse.json({ data: { id: "ingestion-123", attributes: {} } }), + ), + ); + + const response = await POST(uploadRequest()); + + expect(response.status).toBe(502); + await expect(response.json()).resolves.toEqual({ + error: "Unable to start the import. Please try again.", + }); + }); +}); diff --git a/ui/app/api/ingestions/route.ts b/ui/app/api/ingestions/route.ts new file mode 100644 index 0000000000..d8bf4a0ce6 --- /dev/null +++ b/ui/app/api/ingestions/route.ts @@ -0,0 +1,114 @@ +import { NextResponse } from "next/server"; + +import { apiBaseUrl, getAuthHeaders } from "@/lib"; +import { parseIngestion } from "@/lib/ingestions"; +import { isCloud } from "@/lib/shared/env"; + +export const dynamic = "force-dynamic"; +export const runtime = "nodejs"; + +const INVALID_INGESTION_RESPONSE = + "Unable to start the import. Please try again."; +const INGESTION_REJECTION_BY_CODE = { + invalid: "The report is not a valid Prowler OCSF finding report.", + subscription_required: + "A Prowler Cloud subscription is required to import findings.", + permission_denied: "You do not have permission to import findings.", + file_too_large: "The selected file exceeds the allowed upload size.", + rate_limited: "Too many import requests. Please try again shortly.", +} as const; + +const INGESTION_REJECTION_BY_STATUS = { + 400: INGESTION_REJECTION_BY_CODE.invalid, + 402: INGESTION_REJECTION_BY_CODE.subscription_required, + 403: INGESTION_REJECTION_BY_CODE.permission_denied, + 413: INGESTION_REJECTION_BY_CODE.file_too_large, + 429: INGESTION_REJECTION_BY_CODE.rate_limited, +} as const; + +const ingestionRejectionMessage = ( + payload: unknown, + status: number, + fallback: string, +): string => { + if (typeof payload === "object" && payload !== null && "errors" in payload) { + const errors = payload.errors; + if (Array.isArray(errors) && typeof errors[0]?.code === "string") { + const message = + INGESTION_REJECTION_BY_CODE[ + errors[0].code as keyof typeof INGESTION_REJECTION_BY_CODE + ]; + if (message) return message; + } + } + + return ( + INGESTION_REJECTION_BY_STATUS[ + status as keyof typeof INGESTION_REJECTION_BY_STATUS + ] ?? fallback + ); +}; + +export async function POST(request: Request) { + if (!isCloud()) return new Response(null, { status: 404 }); + + const headers = await getAuthHeaders({ contentType: false }); + const contentType = request.headers.get("content-type"); + const contentLength = request.headers.get("content-length"); + + if (contentType) headers["Content-Type"] = contentType; + // Without the length the stream is forwarded chunked, and the ingestion API + // parses no file out of a chunked multipart body: refuse rather than spend + // the upload on a request that cannot succeed. + if (!contentLength) { + return NextResponse.json( + { error: INVALID_INGESTION_RESPONSE }, + { status: 411 }, + ); + } + headers["Content-Length"] = contentLength; + + const upstreamRequest: RequestInit & { duplex: "half" } = { + method: "POST", + headers, + body: request.body, + duplex: "half", + cache: "no-store", + }; + let upstreamResponse: Response; + try { + upstreamResponse = await fetch(`${apiBaseUrl}/ingestions`, upstreamRequest); + } catch { + return NextResponse.json( + { error: INVALID_INGESTION_RESPONSE }, + { status: 502 }, + ); + } + const payload = await upstreamResponse.json().catch(() => undefined); + + if (!upstreamResponse.ok) { + return NextResponse.json( + { + error: ingestionRejectionMessage( + payload, + upstreamResponse.status, + INVALID_INGESTION_RESPONSE, + ), + }, + { status: upstreamResponse.status }, + ); + } + + const ingestion = parseIngestion(payload); + if (!ingestion) { + return NextResponse.json( + { error: INVALID_INGESTION_RESPONSE }, + { status: 502 }, + ); + } + + return NextResponse.json( + { data: ingestion }, + { status: upstreamResponse.status }, + ); +} diff --git a/ui/auth.config.test.ts b/ui/auth.config.test.ts index a95461cb59..5815f31496 100644 --- a/ui/auth.config.test.ts +++ b/ui/auth.config.test.ts @@ -35,8 +35,11 @@ const RESTRICTED_PERMISSIONS: RolePermissionAttributes = { manage_account: false, manage_providers: false, manage_scans: false, + manage_ingestions: false, manage_integrations: false, + manage_billing: false, manage_alerts: false, + manage_lighthouse_ai_configuration: false, unlimited_visibility: false, }; diff --git a/ui/auth.config.ts b/ui/auth.config.ts index ec6880e193..c741534d24 100644 --- a/ui/auth.config.ts +++ b/ui/auth.config.ts @@ -56,6 +56,7 @@ const DEFAULT_PERMISSIONS: RolePermissionAttributes = { manage_account: false, manage_providers: false, manage_scans: false, + manage_ingestions: false, manage_integrations: false, manage_billing: false, manage_alerts: false, @@ -95,7 +96,7 @@ const toTokenUser = (user?: TokenUserInput): TokenUser => email: user?.email ?? undefined, companyName: user?.companyName ?? user?.company, dateJoined: user?.dateJoined, - permissions: user?.permissions ?? { ...DEFAULT_PERMISSIONS }, + permissions: { ...DEFAULT_PERMISSIONS, ...user?.permissions }, }) as TokenUser; type UserMeResponse = Awaited>; diff --git a/ui/changelog.d/import-findings-drag-drop.added.md b/ui/changelog.d/import-findings-drag-drop.added.md new file mode 100644 index 0000000000..ee9c9b931c --- /dev/null +++ b/ui/changelog.d/import-findings-drag-drop.added.md @@ -0,0 +1 @@ +Finding-report imports from Scans for Cloud and Private Cloud deployments diff --git a/ui/components/scans/import-findings-modal.tsx b/ui/components/scans/import-findings-modal.tsx new file mode 100644 index 0000000000..c367829ea2 --- /dev/null +++ b/ui/components/scans/import-findings-modal.tsx @@ -0,0 +1,316 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import { useState } from "react"; + +import { Button } from "@/components/shadcn/button/button"; +import { FileUploadDropzone } from "@/components/shadcn/file-upload/file-upload-dropzone"; +import { Modal } from "@/components/shadcn/modal/modal"; +import { useToast } from "@/components/shadcn/toast/use-toast"; +import { type Ingestion, type IngestionResponse } from "@/types"; + +import { + type IngestionPollingTarget, + useIngestionPolling, +} from "./use-ingestion-polling"; + +const IMPORT_STATE = { + IDLE: "idle", + READY: "ready", + UPLOADING: "uploading", + TRACKING: "tracking", + TRACKING_ERROR: "tracking-error", + COMPLETED: "completed", + FAILED: "failed", + INVALID: "invalid", +} as const; + +interface IdleImportState { + type: typeof IMPORT_STATE.IDLE; +} + +interface ReadyImportState { + type: typeof IMPORT_STATE.READY; + file: File; +} + +interface UploadingImportState { + type: typeof IMPORT_STATE.UPLOADING; + file: File; +} + +interface TrackingImportState { + type: typeof IMPORT_STATE.TRACKING; + file: File; + ingestion: Ingestion; +} + +interface TrackingErrorImportState { + type: typeof IMPORT_STATE.TRACKING_ERROR; + error: string; + file: File; + ingestion: Ingestion; +} + +interface CompletedImportState { + type: typeof IMPORT_STATE.COMPLETED; + ingestion: Ingestion; +} + +interface FailedImportState { + type: typeof IMPORT_STATE.FAILED; + error: string; + file: File; + // Absent when the upload itself was rejected: no job, so no counters. + ingestion?: Ingestion; +} + +interface InvalidImportState { + type: typeof IMPORT_STATE.INVALID; + error: string; +} + +type ImportState = + | IdleImportState + | ReadyImportState + | UploadingImportState + | TrackingImportState + | TrackingErrorImportState + | CompletedImportState + | FailedImportState + | InvalidImportState; + +const validateFile = (file: File): string | null => { + if (!file.name.toLowerCase().endsWith(".ocsf.json")) { + return "Choose a Prowler .ocsf.json finding report."; + } + if (file.size === 0) return "The selected file is empty."; + return null; +}; + +const START_ERROR = "Unable to start the import. Please try again."; + +const responseError = async ( + response: Response, + fallback: string, +): Promise => { + const payload = await response.json().catch(() => undefined); + if ( + typeof payload === "object" && + payload !== null && + "error" in payload && + typeof payload.error === "string" + ) { + return payload.error; + } + return fallback; +}; + +export function ImportFindingsModal() { + const router = useRouter(); + const { toast } = useToast(); + const [open, setOpen] = useState(false); + const [state, setState] = useState({ type: IMPORT_STATE.IDLE }); + const polling = useIngestionPolling({ + onCompleted: (ingestion, completedWhileHidden) => { + router.refresh(); + if (completedWhileHidden) { + toast({ + title: "Findings import completed", + description: "Imported findings are now available in Scans.", + }); + } + setState({ type: IMPORT_STATE.COMPLETED, ingestion }); + }, + onFailed: ({ file, ingestion }) => { + setState({ + type: IMPORT_STATE.FAILED, + error: + "Import failed. Retry the same file or select a different report.", + file, + ingestion, + }); + }, + onProgress: ({ file, ingestion }) => { + setState({ type: IMPORT_STATE.TRACKING, file, ingestion }); + }, + onTrackingError: ({ file, ingestion }, error) => { + setState({ + type: IMPORT_STATE.TRACKING_ERROR, + error, + file, + ingestion, + }); + }, + }); + + const handleFileSelect = (file?: File) => { + if (!file) { + setState({ type: IMPORT_STATE.IDLE }); + return; + } + + const error = validateFile(file); + setState( + error + ? { type: IMPORT_STATE.INVALID, error } + : { type: IMPORT_STATE.READY, file }, + ); + }; + + const handleOpenChange = (nextOpen: boolean) => { + polling.setDialogVisible(nextOpen); + // A job that completed while hidden leaves a summary nobody dismissed. + // Reset it on the next open so the dropzone is available again. + if (nextOpen && state.type === IMPORT_STATE.COMPLETED) { + setState({ type: IMPORT_STATE.IDLE }); + } + // Dismissing never aborts the request: resetting here would drop the + // accepted job and re-enable submit for a second, concurrent POST. + if ( + !nextOpen && + state.type !== IMPORT_STATE.UPLOADING && + state.type !== IMPORT_STATE.TRACKING && + state.type !== IMPORT_STATE.TRACKING_ERROR + ) { + setState({ type: IMPORT_STATE.IDLE }); + } + setOpen(nextOpen); + }; + + const upload = async (file: File) => { + setState({ type: IMPORT_STATE.UPLOADING, file }); + const formData = new FormData(); + formData.set("file", file); + const response = await fetch("/api/ingestions", { + method: "POST", + body: formData, + }).catch(() => undefined); + if (!response || !response.ok) { + setState({ + type: IMPORT_STATE.FAILED, + error: response + ? await responseError(response, START_ERROR) + : START_ERROR, + file, + }); + return; + } + + const payload = (await response.json()) as IngestionResponse; + const target: IngestionPollingTarget = { file, ingestion: payload.data }; + if (!polling.start(target)) return; + setState({ type: IMPORT_STATE.TRACKING, ...target }); + }; + + const submit = async () => { + if (state.type !== IMPORT_STATE.READY) return; + await upload(state.file); + }; + + const file = + state.type === IMPORT_STATE.READY || + state.type === IMPORT_STATE.UPLOADING || + state.type === IMPORT_STATE.FAILED || + state.type === IMPORT_STATE.TRACKING || + state.type === IMPORT_STATE.TRACKING_ERROR + ? state.file + : undefined; + const isSubmitting = state.type === IMPORT_STATE.UPLOADING; + const completed = state.type === IMPORT_STATE.COMPLETED; + + return ( + <> + + +
+ {completed ? ( +

+ Import completed: {state.ingestion.totalRecords} total records,{" "} + {state.ingestion.processedRecords} processed,{" "} + {state.ingestion.invalidRecords} invalid. +

+ ) : ( + <> +
+ +
+ {state.type === IMPORT_STATE.INVALID && ( +

{state.error}

+ )} + {state.type === IMPORT_STATE.FAILED && ( + <> +

{state.error}

+ {state.ingestion && ( +

+ Reported progress: {state.ingestion.processedRecords} of{" "} + {state.ingestion.totalRecords} records processed,{" "} + {state.ingestion.invalidRecords} invalid. +

+ )} + + + )} + {state.type === IMPORT_STATE.TRACKING && ( +

Import is {state.ingestion.status}.

+ )} + {state.type === IMPORT_STATE.TRACKING_ERROR && ( + <> +

{state.error}

+ + + )} + + + )} +
+
+ + ); +} diff --git a/ui/components/scans/scans-page-shell.test.tsx b/ui/components/scans/scans-page-shell.test.tsx index 5d953e1ec3..b702f2cdf7 100644 --- a/ui/components/scans/scans-page-shell.test.tsx +++ b/ui/components/scans/scans-page-shell.test.tsx @@ -178,24 +178,6 @@ describe("ScansPageShell", () => { useScansStore.getState().closeLaunchScanModal(); }); - it("does not render an imported findings tab", () => { - vi.stubEnv("UI_CLOUD_ENABLED", "false"); - - render( - -
Scans table
-
, - ); - - expect( - screen.queryByRole("tab", { name: /imported findings/i }), - ).not.toBeInTheDocument(); - expect( - screen.queryByRole("button", { name: /import findings/i }), - ).not.toBeInTheDocument(); - expect(screen.queryByRole("dialog")).not.toBeInTheDocument(); - }); - it("uses the shared scan filter bar for scan filters", () => { vi.stubEnv("UI_CLOUD_ENABLED", "false"); @@ -245,6 +227,72 @@ describe("ScansPageShell", () => { expect(screen.getByRole("combobox", { name: /all types/i })).toBeVisible(); }); + it.each(["Cloud", "Private Cloud"])( + "shows Import Findings in %s with Manage Ingestions", + () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "true"); + + // When + render( + +
Scans table
+
, + ); + + // Then + expect( + screen.getByRole("button", { name: /import findings/i }), + ).toBeVisible(); + }, + ); + + it("hides Import Findings without Manage Ingestions", () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "true"); + + // When + render( + +
Scans table
+
, + ); + + // Then + expect( + screen.queryByRole("button", { name: /import findings/i }), + ).not.toBeInTheDocument(); + }); + + it("hides Import Findings in OSS and Local Server", () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "false"); + + // When + render( + +
Scans table
+
, + ); + + // Then + expect( + screen.queryByRole("button", { name: /import findings/i }), + ).not.toBeInTheDocument(); + }); + it("shows the CLI import banner in Cloud", () => { vi.stubEnv("UI_CLOUD_ENABLED", "true"); diff --git a/ui/components/scans/scans-page-shell.tsx b/ui/components/scans/scans-page-shell.tsx index 8209957879..6af2c436fd 100644 --- a/ui/components/scans/scans-page-shell.tsx +++ b/ui/components/scans/scans-page-shell.tsx @@ -28,6 +28,7 @@ import type { ScanScheduleCapability } from "@/types/schedules"; const viewFirstScanFlow = getFlowById("view-first-scan")!; import { CliImportBanner } from "./cli-import-banner"; +import { ImportFindingsModal } from "./import-findings-modal"; import { LaunchScanModal } from "./launch-scan-modal"; import { ScansFilterBar } from "./scans-filter-bar"; import { ScansProvidersEmptyState } from "./scans-providers-empty-state"; @@ -37,6 +38,7 @@ interface ScansPageShellProps { providers: ProviderProps[]; providerGroups?: ProviderGroup[]; hasManageScansPermission: boolean; + hasManageIngestionsPermission?: boolean; activeScanCount?: number; children: ReactNode; /** Cloud overlay seam for the launch-scan modal. */ @@ -48,6 +50,7 @@ export function ScansPageShell({ providers, providerGroups = [], hasManageScansPermission, + hasManageIngestionsPermission = false, activeScanCount = 0, children, scanScheduleCapability, @@ -155,6 +158,9 @@ export function ScansPageShell({ > Launch Scan + {isCloudEnvironment && hasManageIngestionsPermission && ( + + )} {isCloudEnvironment && } diff --git a/ui/components/scans/use-ingestion-polling.ts b/ui/components/scans/use-ingestion-polling.ts new file mode 100644 index 0000000000..fb9bab5729 --- /dev/null +++ b/ui/components/scans/use-ingestion-polling.ts @@ -0,0 +1,157 @@ +"use client"; + +import { useEffect, useRef } from "react"; + +import { INGESTION_STATUS, type Ingestion } from "@/types"; + +const POLL_INTERVAL_MS = 5000; +// 60 polls at 5s = ~5 min of watching; timing out ends the watch, not the job. +const MAX_POLL_ATTEMPTS = 60; +const STATUS_ERROR = "Unable to check the import status. Please try again."; +const STATUS_TIMEOUT = + "Import is taking longer than expected — it may still be running in the background."; + +export interface IngestionPollingTarget { + file: File; + ingestion: Ingestion; +} + +interface UseIngestionPollingOptions { + onCompleted: (ingestion: Ingestion, completedWhileHidden: boolean) => void; + onFailed: (target: IngestionPollingTarget) => void; + onProgress: (target: IngestionPollingTarget) => void; + onTrackingError: (target: IngestionPollingTarget, error: string) => void; +} + +const isTerminal = (ingestion: Ingestion): boolean => + ingestion.status === INGESTION_STATUS.COMPLETED || + ingestion.status === INGESTION_STATUS.FAILED; + +const responseError = async ( + response: Response, + fallback: string, +): Promise => { + const payload = await response.json().catch(() => undefined); + if ( + typeof payload === "object" && + payload !== null && + "error" in payload && + typeof payload.error === "string" + ) { + return payload.error; + } + return fallback; +}; + +export const useIngestionPolling = ({ + onCompleted, + onFailed, + onProgress, + onTrackingError, +}: UseIngestionPollingOptions) => { + const controllerRef = useRef(null); + const dialogVisibleRef = useRef(false); + const mountedRef = useRef(true); + const timeoutRef = useRef(null); + + const stop = () => { + controllerRef.current?.abort(); + controllerRef.current = null; + if (timeoutRef.current !== null) { + window.clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + }; + + const setDialogVisible = (visible: boolean) => { + dialogVisibleRef.current = visible; + }; + + const start = (initialTarget: IngestionPollingTarget): boolean => { + if (!mountedRef.current) return false; + stop(); + + const controller = new AbortController(); + controllerRef.current = controller; + let attempts = 0; + let target = initialTarget; + + const finish = () => { + if (controllerRef.current === controller) { + controllerRef.current = null; + } + timeoutRef.current = null; + }; + + const poll = async () => { + attempts += 1; + + try { + const response = await fetch(`/api/ingestions/${target.ingestion.id}`, { + signal: controller.signal, + }); + if (!response.ok) { + const error = await responseError(response, STATUS_ERROR); + if (controller.signal.aborted) return; + finish(); + onTrackingError(target, error); + return; + } + + const payload = (await response.json()) as { + data?: Ingestion; + }; + if (controller.signal.aborted) return; + + const ingestion = payload.data; + if (!ingestion || !isTerminal(ingestion)) { + target = { + file: target.file, + ingestion: ingestion ?? target.ingestion, + }; + + if (attempts >= MAX_POLL_ATTEMPTS) { + finish(); + onTrackingError(target, STATUS_TIMEOUT); + return; + } + + onProgress(target); + timeoutRef.current = window.setTimeout( + () => void poll(), + POLL_INTERVAL_MS, + ); + return; + } + + finish(); + if (ingestion.status === INGESTION_STATUS.COMPLETED) { + onCompleted(ingestion, !dialogVisibleRef.current); + return; + } + + onFailed({ file: target.file, ingestion }); + } catch { + if (controller.signal.aborted) return; + finish(); + onTrackingError(target, STATUS_ERROR); + } + }; + + void poll(); + return true; + }; + + useEffect(() => { + mountedRef.current = true; + return () => { + mountedRef.current = false; + controllerRef.current?.abort(); + if (timeoutRef.current !== null) { + window.clearTimeout(timeoutRef.current); + } + }; + }, []); + + return { setDialogVisible, start, stop }; +}; diff --git a/ui/components/shadcn/file-upload/file-upload-dropzone.tsx b/ui/components/shadcn/file-upload/file-upload-dropzone.tsx index 120bdea59d..e15cb2c25c 100644 --- a/ui/components/shadcn/file-upload/file-upload-dropzone.tsx +++ b/ui/components/shadcn/file-upload/file-upload-dropzone.tsx @@ -1,10 +1,27 @@ "use client"; import { FileUp } from "lucide-react"; -import { type DragEvent, type ReactNode, useId, useState } from "react"; +import { + type ChangeEvent, + type DragEvent, + type KeyboardEvent, + type ReactNode, + useId, + useRef, + useState, +} from "react"; import { cn } from "@/lib/utils"; +const KB = 1024; +const MB = KB * 1024; + +// Not toLocaleString: a locale-grouped "15.002 KB" reads as 15 KB in es-ES. +function formatFileSize(bytes: number) { + const kb = Math.ceil(bytes / KB); + return kb < KB ? `${kb} KB` : `${(bytes / MB).toFixed(1)} MB`; +} + interface FileUploadDropzoneProps { file?: File | null; onFileSelect: (file?: File) => void; @@ -14,6 +31,7 @@ interface FileUploadDropzoneProps { emptyDescription?: string; selectText?: string; icon?: ReactNode; + disabled?: boolean; } export function FileUploadDropzone({ @@ -25,21 +43,40 @@ export function FileUploadDropzone({ emptyDescription = "or", selectText = "Select File", icon = , + disabled = false, }: FileUploadDropzoneProps) { const inputId = useId(); + const inputRef = useRef(null); const [isDragging, setIsDragging] = useState(false); const handleDrop = (event: DragEvent) => { event.preventDefault(); setIsDragging(false); + if (disabled) return; onFileSelect(event.dataTransfer.files[0]); }; + const handleKeyDown = (event: KeyboardEvent) => { + if (disabled || (event.key !== "Enter" && event.key !== " ")) return; + event.preventDefault(); + inputRef.current?.click(); + }; + + const handleChange = (event: ChangeEvent) => { + onFileSelect(event.target.files?.[0]); + event.target.value = ""; + }; + return ( ); diff --git a/ui/hooks/use-auth.ts b/ui/hooks/use-auth.ts index 0946fc7677..4e5d5ea76c 100644 --- a/ui/hooks/use-auth.ts +++ b/ui/hooks/use-auth.ts @@ -11,6 +11,7 @@ export function useAuth() { manage_account: false, manage_providers: false, manage_scans: false, + manage_ingestions: false, manage_integrations: false, manage_billing: false, manage_alerts: false, diff --git a/ui/lib/ingestions.ts b/ui/lib/ingestions.ts new file mode 100644 index 0000000000..ed783212b7 --- /dev/null +++ b/ui/lib/ingestions.ts @@ -0,0 +1,55 @@ +import { + INGESTION_STATUS, + type Ingestion, + type IngestionStatus, +} from "@/types"; + +interface JsonApiIngestionSummary { + total?: unknown; + processed?: unknown; + invalid?: unknown; +} + +interface JsonApiIngestionAttributes { + status?: unknown; + summary?: JsonApiIngestionSummary; +} + +interface JsonApiIngestionData { + id?: unknown; + attributes?: JsonApiIngestionAttributes; +} + +interface JsonApiIngestionResponse { + data?: JsonApiIngestionData; +} + +const isIngestionStatus = (value: unknown): value is IngestionStatus => + Object.values(INGESTION_STATUS).includes(value as IngestionStatus); + +// Counts are absent until the job reports them: read as 0, not a failure. +const recordCount = (value: unknown): number => + typeof value === "number" ? value : 0; + +export const parseIngestion = (payload: unknown): Ingestion | null => { + const data = (payload as JsonApiIngestionResponse)?.data; + const attributes = data?.attributes; + + if ( + typeof data?.id !== "string" || + data.id === "" || + !isIngestionStatus(attributes?.status) + ) { + return null; + } + + const summary = attributes.summary; + + return { + id: data.id, + status: attributes.status, + totalRecords: recordCount(summary?.total), + processedRecords: recordCount(summary?.processed), + invalidRecords: recordCount(summary?.invalid), + }; +}; diff --git a/ui/types/index.ts b/ui/types/index.ts index 213f41f5b9..ac5812aa20 100644 --- a/ui/types/index.ts +++ b/ui/types/index.ts @@ -5,6 +5,7 @@ export * from "./filters"; export * from "./findings-table"; export * from "./findings-triage"; export * from "./formSchemas"; +export * from "./ingestions"; export * from "./organizations"; export * from "./processors"; export * from "./provider-wizard"; diff --git a/ui/types/ingestions.ts b/ui/types/ingestions.ts new file mode 100644 index 0000000000..b3732d0ddc --- /dev/null +++ b/ui/types/ingestions.ts @@ -0,0 +1,21 @@ +export const INGESTION_STATUS = { + PENDING: "pending", + PROCESSING: "processing", + COMPLETED: "completed", + FAILED: "failed", +} as const; + +export type IngestionStatus = + (typeof INGESTION_STATUS)[keyof typeof INGESTION_STATUS]; + +export interface Ingestion { + id: string; + status: IngestionStatus; + totalRecords: number; + processedRecords: number; + invalidRecords: number; +} + +export interface IngestionResponse { + data: Ingestion; +} diff --git a/ui/types/users.ts b/ui/types/users.ts index c9b43494b3..56dfe7c3e5 100644 --- a/ui/types/users.ts +++ b/ui/types/users.ts @@ -87,6 +87,7 @@ export const PERMISSION_KEY = { MANAGE_ACCOUNT: "manage_account", MANAGE_PROVIDERS: "manage_providers", MANAGE_SCANS: "manage_scans", + MANAGE_INGESTIONS: "manage_ingestions", MANAGE_INTEGRATIONS: "manage_integrations", MANAGE_BILLING: "manage_billing", MANAGE_ALERTS: "manage_alerts", @@ -98,7 +99,7 @@ export type PermissionKey = (typeof PERMISSION_KEY)[keyof typeof PERMISSION_KEY]; export type RolePermissionAttributes = Pick< - RoleDetail["attributes"], + RoleDetailAttributes, PermissionKey >; @@ -110,43 +111,54 @@ export const TENANT_MEMBERSHIP_ROLE = { export type TenantMembershipRole = (typeof TENANT_MEMBERSHIP_ROLE)[keyof typeof TENANT_MEMBERSHIP_ROLE]; +export interface RoleDetailAttributes { + name: string; + manage_users: boolean; + manage_account: boolean; + manage_providers: boolean; + manage_scans: boolean; + manage_ingestions?: boolean; + manage_integrations: boolean; + manage_billing?: boolean; + manage_alerts?: boolean; + manage_lighthouse_ai_configuration?: boolean; + unlimited_visibility: boolean; + permission_state?: string; + inserted_at?: string; + updated_at?: string; +} + export interface RoleDetail { id: string; type: "roles"; - attributes: { - name: string; - manage_users: boolean; - manage_account: boolean; - manage_providers: boolean; - manage_scans: boolean; - manage_integrations: boolean; - manage_billing?: boolean; - manage_alerts?: boolean; - manage_lighthouse_ai_configuration?: boolean; - unlimited_visibility: boolean; - permission_state?: string; - inserted_at?: string; - updated_at?: string; - }; + attributes: RoleDetailAttributes; +} + +export interface MembershipDetailAttributes { + role: string; + date_joined: string; + [key: string]: unknown; +} + +export interface MembershipTenantIdentifier { + type: string; + id: string; +} + +export interface MembershipTenantRelationship { + data: MembershipTenantIdentifier; +} + +export interface MembershipDetailRelationships { + tenant: MembershipTenantRelationship; + [key: string]: unknown; } export interface MembershipDetailData { id: string; type: "memberships"; - attributes: { - role: string; - date_joined: string; - [key: string]: any; - }; - relationships: { - tenant: { - data: { - type: string; - id: string; - }; - }; - [key: string]: any; - }; + attributes: MembershipDetailAttributes; + relationships: MembershipDetailRelationships; } export interface UserDataWithRoles From 13a31d922555315111d8ada61ec9fea5a4dd0d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Mon, 31 Aug 2026 17:36:19 +0200 Subject: [PATCH 08/77] feat(mcp): raise instead of returning error objects in the Prowler Docs tools (#12534) Co-authored-by: Claude Opus 5 (1M context) --- .../mcp-docs-search-swallowed-errors.fixed.md | 1 + .../prowler_documentation/search_engine.py | 127 +++++++++--------- .../prowler_documentation/server.py | 13 +- .../prowler_documentation/test_server.py | 69 +++++++++- 4 files changed, 142 insertions(+), 68 deletions(-) create mode 100644 mcp_server/changelog.d/mcp-docs-search-swallowed-errors.fixed.md diff --git a/mcp_server/changelog.d/mcp-docs-search-swallowed-errors.fixed.md b/mcp_server/changelog.d/mcp-docs-search-swallowed-errors.fixed.md new file mode 100644 index 0000000000..d24445ea71 --- /dev/null +++ b/mcp_server/changelog.d/mcp-docs-search-swallowed-errors.fixed.md @@ -0,0 +1 @@ +`prowler_docs_search` no longer reports a failed search as zero matches or an unreadable answer as a bad search term, and `prowler_docs_get_document` no longer reports a failed fetch as a missing page diff --git a/mcp_server/prowler_mcp_server/prowler_documentation/search_engine.py b/mcp_server/prowler_mcp_server/prowler_documentation/search_engine.py index 1eb1d10820..990a225239 100644 --- a/mcp_server/prowler_mcp_server/prowler_documentation/search_engine.py +++ b/mcp_server/prowler_mcp_server/prowler_documentation/search_engine.py @@ -2,6 +2,7 @@ import httpx from pydantic import BaseModel, Field from prowler_mcp_server import __version__ +from prowler_mcp_server.lib.errors import parse_json_response class SearchResult(BaseModel): @@ -58,8 +59,7 @@ class ProwlerDocsSearchEngine: ) def search(self, query: str, page_size: int = 5) -> list[SearchResult]: - """ - Search documentation using Mintlify API. + """Search documentation using Mintlify API. Args: query: Search query string @@ -69,82 +69,85 @@ class ProwlerDocsSearchEngine: Returns: list of search results + + Raises: + httpx.HTTPError: If the search request failed, which is not the same + answer as no matches + UpstreamInvalidResponse: If the answer is not JSON, which is the + documentation site's fault and not the search term's """ - try: - # Make request to Mintlify API - response = self.mintlify_client.post( - self.api_base_url, - json={"query": query, "filters": {}}, - ) - response.raise_for_status() - data = response.json() + # Make request to Mintlify API + response = self.mintlify_client.post( + self.api_base_url, + json={"query": query, "filters": {}}, + ) + response.raise_for_status() + # Not `response.json()`: the decode error it raises is a ValueError, which + # the shared classifier reads as a malformed argument and answers by + # telling the caller to fix a search term that was never the problem. + data = parse_json_response(response) - # Parse results - results = [] - for match in data.get("results", [])[:page_size]: - metadata = match.get("metadata", {}) - breadcrumbs = metadata.get("breadcrumbs", []) - doc_path = match.get("page", "") + # Parse results + results = [] + for match in data.get("results", [])[:page_size]: + metadata = match.get("metadata", {}) + breadcrumbs = metadata.get("breadcrumbs", []) + doc_path = match.get("page", "") - # A match is one section of a page rather than the page: the - # heading it was found under is its header, and the page's own - # title is the last step of its breadcrumb trail. - section = match.get("header", "") - title = breadcrumbs[-1] if breadcrumbs else section + # A match is one section of a page rather than the page: the + # heading it was found under is its header, and the page's own + # title is the last step of its breadcrumb trail. + section = match.get("header", "") + title = breadcrumbs[-1] if breadcrumbs else section - # Sent as "" for the section a page opens with and as null for - # the pages that have no anchors at all; both mean the page. - anchor = metadata.get("hash") - url = f"{self.docs_base_url}/{doc_path}" - if anchor: - url = f"{url}#{anchor}" + # Sent as "" for the section a page opens with and as null for + # the pages that have no anchors at all; both mean the page. + anchor = metadata.get("hash") + url = f"{self.docs_base_url}/{doc_path}" + if anchor: + url = f"{url}#{anchor}" - results.append( - SearchResult( - path=doc_path, - title=title, - section=section, - breadcrumbs=breadcrumbs, - url=url, - excerpt=match.get("content", ""), - score=match.get("score", 0.0), - ) + results.append( + SearchResult( + path=doc_path, + title=title, + section=section, + breadcrumbs=breadcrumbs, + url=url, + excerpt=match.get("content", ""), + score=match.get("score", 0.0), ) + ) - return results - - except Exception as e: - # Return empty list on error - print(f"Search error: {e}") - return [] + return results def get_document(self, doc_path: str) -> str | None: - """ - Get full document content from Mintlify documentation. + """Get full document content from Mintlify documentation. Args: doc_path: Path to the documentation file (e.g., "getting-started/installation") Returns: - Full markdown content of the documentation, or None if not found + Full markdown content of the documentation, or None if there is no + page at that path + + Raises: + httpx.HTTPError: If the fetch failed for any reason other than a 404 """ - try: - # Clean up the path - doc_path = doc_path.rstrip("/") + # Clean up the path + doc_path = doc_path.rstrip("/") - # Add .md extension if not present (Mintlify serves both .md and .mdx) - if not doc_path.endswith(".md"): - doc_path = f"{doc_path}.md" + # Add .md extension if not present (Mintlify serves both .md and .mdx) + if not doc_path.endswith(".md"): + doc_path = f"{doc_path}.md" - # Construct Mintlify URL - url = f"{self.docs_base_url}/{doc_path}" + # Construct Mintlify URL + url = f"{self.docs_base_url}/{doc_path}" - # Fetch the documentation page - response = self.docs_client.get(url) - response.raise_for_status() - - return response.text - - except Exception as e: - print(f"Error fetching document: {e}") + # Fetch the documentation page + response = self.docs_client.get(url) + if response.status_code == 404: return None + response.raise_for_status() + + return response.text diff --git a/mcp_server/prowler_mcp_server/prowler_documentation/server.py b/mcp_server/prowler_mcp_server/prowler_documentation/server.py index de0756a505..1121d7c419 100644 --- a/mcp_server/prowler_mcp_server/prowler_documentation/server.py +++ b/mcp_server/prowler_mcp_server/prowler_documentation/server.py @@ -1,6 +1,7 @@ from typing import Any from fastmcp import FastMCP +from fastmcp.exceptions import ToolError from pydantic import Field from prowler_mcp_server.lib.types import NonBlankStr @@ -9,7 +10,7 @@ from prowler_mcp_server.prowler_documentation.search_engine import ( ) # Initialize FastMCP server -docs_mcp_server = FastMCP("prowler-docs") +docs_mcp_server = FastMCP("prowler-docs", mask_error_details=True) prowler_docs_search_engine = ProwlerDocsSearchEngine() @@ -56,6 +57,10 @@ def get_document( """ content: str | None = prowler_docs_search_engine.get_document(doc_path) if content is None: - return {"error": f"Document '{doc_path}' not found."} - else: - return {"content": content} + # No `from`: this names the path asked for and the tool that produces a + # valid one, neither of which the shared classifier can know. + raise ToolError( + f"The Prowler documentation has no page at '{doc_path}'. Use " + "prowler_docs_search and pass the 'path' field of a result verbatim." + ) + return {"content": content} diff --git a/mcp_server/tests/prowler_documentation/test_server.py b/mcp_server/tests/prowler_documentation/test_server.py index da5e9f17f4..67ee57decf 100644 --- a/mcp_server/tests/prowler_documentation/test_server.py +++ b/mcp_server/tests/prowler_documentation/test_server.py @@ -1,7 +1,9 @@ -"""Tests for the Prowler documentation search tool. +"""Tests for the Prowler documentation tools. Mintlify moved the docs search to a new endpoint that answers with page -sections, so a result is a part of a page and has to read as one. +sections, so a result is a part of a page and has to read as one. And a failed +request must not reach an agent as "the documentation has nothing on this", +which is an answer it would act on, confidently and wrongly. """ import json @@ -9,6 +11,7 @@ import json from fastmcp import Client SEARCH = "/api/search/prowler" +DOC = "/getting-started/installation.md" def search_match( @@ -107,3 +110,65 @@ async def test_page_size_caps_a_response_the_api_did_not_size( ) assert len(result.data) == 2 + + +async def test_a_search_that_failed_is_not_reported_as_no_matches( + mcp_root_server, docs_router +): + """An empty list is an answer. A failed request is not, and must not look like one.""" + docs_router.add("POST", SEARCH, status=500, text="upstream error") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp("prowler_docs_search", {"term": "install"}) + + assert result.isError is True + assert result.structuredContent is None + + +async def test_a_missing_page_fails_and_names_the_tool_that_finds_a_valid_path( + mcp_root_server, docs_router +): + """A 404 answers the question, and still reaches the agent as an error.""" + docs_router.add("GET", DOC, status=404, text="Not Found") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_docs_get_document", {"doc_path": "getting-started/installation"} + ) + + assert result.isError is True + assert "prowler_docs_search" in result.content[0].text + + +async def test_a_fetch_that_failed_is_not_reported_as_a_missing_page( + mcp_root_server, docs_router +): + """Only a 404 answers the question; every other status left it unanswered.""" + docs_router.add("GET", DOC, status=503, text="upstream error") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp( + "prowler_docs_get_document", {"doc_path": "getting-started/installation"} + ) + + assert result.isError is True + assert "no page at" not in result.content[0].text + + +async def test_an_unreadable_body_is_not_reported_as_a_bad_search_term( + mcp_root_server, docs_router +): + """An edge serving HTML is the site's fault; the caller has no term to fix.""" + docs_router.add("POST", SEARCH, status=200, text="edge error page") + + async with Client(mcp_root_server) as client: + result = await client.call_tool_mcp("prowler_docs_search", {"term": "install"}) + + assert result.isError is True + message = result.content[0].text + # Named as the upstream at fault, and explicitly not the caller's arguments, + # which is the story the shared ValueError branch would otherwise tell. + assert "leaves.mintlify.com" in message + assert "changing them will not help" in message + # The body it choked on is upstream text, which this server never relays. + assert "edge error page" not in message From 587c47bfe2e7a5f1cf82d7c7a78607172091a29c Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Mon, 31 Aug 2026 18:00:46 +0200 Subject: [PATCH 09/77] feat(api): add finding labels, finding URL and tenant info to Jira issues (#12540) Co-authored-by: Josema Camacho --- api/.env.example | 4 + .../jira-finding-labels-url.added.md | 1 + api/src/backend/config/django/base.py | 5 + api/src/backend/tasks/jobs/integrations.py | 73 ++++++++- .../backend/tasks/tests/test_integrations.py | 139 +++++++++++++++++- api/uv.lock | 73 ++++++++- .../prowler-app-jira-integration.mdx | 12 ++ 7 files changed, 301 insertions(+), 6 deletions(-) create mode 100644 api/changelog.d/jira-finding-labels-url.added.md diff --git a/api/.env.example b/api/.env.example index f97d868890..c9300ab6b9 100644 --- a/api/.env.example +++ b/api/.env.example @@ -59,5 +59,9 @@ DJANGO_GITHUB_OAUTH_CLIENT_ID="" DJANGO_GITHUB_OAUTH_CLIENT_SECRET="" DJANGO_GITHUB_OAUTH_CALLBACK_URL="" +# Public base URL of the Prowler UI, used to link Jira issues back to findings. +# Leave empty to omit the link. +DJANGO_UI_BASE_URL="" + # Deletion Task Batch Size DJANGO_DELETION_BATCH_SIZE=5000 diff --git a/api/changelog.d/jira-finding-labels-url.added.md b/api/changelog.d/jira-finding-labels-url.added.md new file mode 100644 index 0000000000..e16b26b77d --- /dev/null +++ b/api/changelog.d/jira-finding-labels-url.added.md @@ -0,0 +1 @@ +Jira issues created from Prowler Cloud now carry the `prowler`, `prowler-`, `prowler-`, `prowler-`, and `prowler-finding-` labels, a link back to the finding when `DJANGO_UI_BASE_URL` is configured, and the tenant name diff --git a/api/src/backend/config/django/base.py b/api/src/backend/config/django/base.py index a079942600..b967110c10 100644 --- a/api/src/backend/config/django/base.py +++ b/api/src/backend/config/django/base.py @@ -303,6 +303,11 @@ SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin" DJANGO_DELETION_BATCH_SIZE = env.int("DJANGO_DELETION_BATCH_SIZE", 5000) +# Public base URL of the Prowler UI (for example https://cloud.prowler.com). Used to +# build links back to findings in outbound integrations such as Jira. Empty by +# default, so self-hosted deployments emit no links unless they configure it. +UI_BASE_URL = env.str("DJANGO_UI_BASE_URL", "").rstrip("/") + # SAML requirement CSRF_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True diff --git a/api/src/backend/tasks/jobs/integrations.py b/api/src/backend/tasks/jobs/integrations.py index 303d28c139..3fedcdc83a 100644 --- a/api/src/backend/tasks/jobs/integrations.py +++ b/api/src/backend/tasks/jobs/integrations.py @@ -2,13 +2,16 @@ import os import time from datetime import UTC, datetime from glob import glob +from urllib.parse import quote from api.db_router import READ_REPLICA_ALIAS, MainRouter from api.db_utils import REPLICA_MAX_ATTEMPTS, REPLICA_RETRY_BASE_DELAY, rls_transaction from api.models import Finding, Integration, Provider +from api.rls import Tenant from api.utils import initialize_prowler_integration, initialize_prowler_provider from celery.utils.log import get_task_logger from config.django.base import DJANGO_FINDINGS_BATCH_SIZE +from django.conf import settings from django.db import OperationalError from prowler.lib.outputs.asff.asff import ASFF from prowler.lib.outputs.compliance.generic.generic import GenericCompliance @@ -16,6 +19,7 @@ from prowler.lib.outputs.csv.csv import CSV from prowler.lib.outputs.finding import Finding as FindingOutput from prowler.lib.outputs.html.html import HTML from prowler.lib.outputs.jira.exceptions.exceptions import JiraBaseException +from prowler.lib.outputs.jira.jira import Jira from prowler.lib.outputs.ocsf.ocsf import OCSF from prowler.providers.aws.aws_provider import AwsProvider from prowler.providers.aws.lib.s3.s3 import S3 @@ -477,6 +481,55 @@ def upload_security_hub_integration( return False +JIRA_LABEL_PREFIX = "prowler" + + +def build_jira_finding_url(finding_uid: str) -> str: + """Build the Prowler UI link for a finding, or "" when no UI base URL is set. + + The link filters by the finding ``uid`` rather than the per-scan record id so + it keeps resolving after the finding is seen again in later scans. + """ + base_url = getattr(settings, "UI_BASE_URL", "") + if not base_url or not finding_uid: + return "" + return f"{base_url}/findings?filter[uid]={quote(finding_uid, safe='')}" + + +def build_jira_issue_labels( + finding_uid: str, provider: str, severity: str, check_id: str +) -> list[str]: + """Build the deterministic label set written to every Jira issue. + + Labels are prefixed to avoid colliding with customer labels and sanitized so + Jira never rejects them; the finding-uid label is what lets a ticket be traced + back (or JQL-filtered) to its finding. + """ + raw_labels = [ + JIRA_LABEL_PREFIX, + f"{JIRA_LABEL_PREFIX}-{provider}" if provider else "", + f"{JIRA_LABEL_PREFIX}-{severity}" if severity else "", + f"{JIRA_LABEL_PREFIX}-{check_id}" if check_id else "", + Jira.build_finding_label(finding_uid), + ] + return Jira.sanitize_labels(raw_labels) + + +def get_tenant_name(tenant_id: str) -> str: + """Return the tenant name for the Jira issue "Tenant Info" row, or "" if unknown. + + The name is informational only, so a lookup failure must never block the send. + """ + try: + return ( + Tenant.objects.filter(id=tenant_id).values_list("name", flat=True).first() + or "" + ) + except Exception: + logger.warning("Could not resolve tenant name for %s", tenant_id) + return "" + + def send_findings_to_jira( tenant_id: str, integration_id: str, @@ -487,6 +540,7 @@ def send_findings_to_jira( with rls_transaction(tenant_id): integration = Integration.objects.get(id=integration_id) jira_integration = initialize_prowler_integration(integration) + tenant_info = get_tenant_name(tenant_id) num_tickets_created = 0 error_messages = [] @@ -519,6 +573,15 @@ def send_findings_to_jira( recommendation = remediation.get("recommendation", {}) remediation_code = remediation.get("code", {}) + provider_type = finding_instance.scan.provider.provider + issue_labels = build_jira_issue_labels( + finding_uid=finding_instance.uid, + provider=provider_type, + severity=finding_instance.severity, + check_id=finding_instance.check_id, + ) + finding_url = build_jira_finding_url(finding_instance.uid) + try: # Send the individual finding to Jira result = jira_integration.send_finding( @@ -527,7 +590,7 @@ def send_findings_to_jira( severity=finding_instance.severity, status=finding_instance.status, status_extended=finding_instance.status_extended or "", - provider=finding_instance.scan.provider.provider, + provider=provider_type, region=region, resource_uid=resource_uid, resource_name=resource_name, @@ -542,6 +605,9 @@ def send_findings_to_jira( compliance=finding_instance.compliance or {}, project_key=project_key, issue_type=issue_type, + issue_labels=issue_labels, + finding_url=finding_url, + tenant_info=tenant_info, ) except JiraBaseException as error: error_message = error.message or JIRA_GENERIC_SEND_ERROR @@ -557,6 +623,11 @@ def send_findings_to_jira( if result: num_tickets_created += 1 + logger.info( + "Finding %s sent to Jira as %s", + finding_id, + result.get("key") if isinstance(result, dict) else result, + ) else: error_message = JIRA_GENERIC_SEND_ERROR logger.error(error_message) diff --git a/api/src/backend/tasks/tests/test_integrations.py b/api/src/backend/tasks/tests/test_integrations.py index a95d02fa7f..421fdb992a 100644 --- a/api/src/backend/tasks/tests/test_integrations.py +++ b/api/src/backend/tasks/tests/test_integrations.py @@ -6,15 +6,20 @@ from api.db_router import READ_REPLICA_ALIAS, MainRouter from api.models import Integration from api.utils import prowler_integration_connection_test from django.db import OperationalError +from django.test import override_settings from prowler.lib.outputs.jira.exceptions.exceptions import ( JiraRefreshTokenError, JiraRequiredCustomFieldsError, ) +from prowler.lib.outputs.jira.jira import Jira from prowler.providers.aws.lib.security_hub.security_hub import SecurityHubConnection from prowler.providers.common.models import Connection from tasks.jobs.integrations import ( + build_jira_finding_url, + build_jira_issue_labels, get_s3_client_from_integration, get_security_hub_client_from_integration, + get_tenant_name, send_findings_to_jira, upload_s3_integration, upload_security_hub_integration, @@ -1696,6 +1701,7 @@ class TestJiraIntegration: finding1 = MagicMock() finding1.id = "finding-1" + finding1.uid = "prowler-aws-check_001-123456789012-us-east-1-my bucket" finding1.check_id = "check_001" finding1.severity = "high" finding1.status = "FAIL" @@ -1724,6 +1730,7 @@ class TestJiraIntegration: finding2 = MagicMock() finding2.id = "finding-2" + finding2.uid = "prowler-azure-check_002-sub/resource" finding2.check_id = "check_002" finding2.severity = "medium" finding2.status = "PASS" @@ -1748,9 +1755,13 @@ class TestJiraIntegration: ] # Call the function - result = send_findings_to_jira( - tenant_id, integration_id, project_key, issue_type, finding_ids - ) + with ( + override_settings(UI_BASE_URL="https://cloud.example.com"), + patch("tasks.jobs.integrations.get_tenant_name", return_value="Acme"), + ): + result = send_findings_to_jira( + tenant_id, integration_id, project_key, issue_type, finding_ids + ) # Assertions assert result == {"created_count": 2, "failed_count": 0} @@ -1773,12 +1784,36 @@ class TestJiraIntegration: assert first_call.kwargs["provider"] == "aws" assert first_call.kwargs["project_key"] == project_key assert first_call.kwargs["issue_type"] == issue_type + # Finding reference: labels, link back and tenant info + assert first_call.kwargs["issue_labels"] == [ + "prowler", + "prowler-aws", + "prowler-high", + "prowler-check_001", + "prowler-finding-prowler-aws-check_001-123456789012-us-east-1-my_bucket", + ] + assert first_call.kwargs["finding_url"] == ( + "https://cloud.example.com/findings?filter[uid]=" + "prowler-aws-check_001-123456789012-us-east-1-my%20bucket" + ) + assert first_call.kwargs["tenant_info"] == "Acme" # Verify second call second_call = mock_jira_integration.send_finding.call_args_list[1] assert second_call.kwargs["check_id"] == "check_002" assert second_call.kwargs["severity"] == "medium" assert second_call.kwargs["status"] == "PASS" + assert second_call.kwargs["issue_labels"] == [ + "prowler", + "prowler-azure", + "prowler-medium", + "prowler-check_002", + "prowler-finding-prowler-azure-check_002-sub/resource", + ] + assert second_call.kwargs["finding_url"] == ( + "https://cloud.example.com/findings?filter[uid]=" + "prowler-azure-check_002-sub%2Fresource" + ) @patch("tasks.jobs.integrations.rls_transaction") @patch("tasks.jobs.integrations.Finding") @@ -2200,3 +2235,101 @@ class TestJiraIntegration: assert call_kwargs["remediation_code_cli"] == "" assert call_kwargs["remediation_code_other"] == "" assert call_kwargs["compliance"] == {} + + +class TestJiraFindingReference: + """Helpers that give Jira issues a stable reference back to the finding.""" + + def test_build_jira_issue_labels(self): + assert build_jira_issue_labels( + finding_uid="prowler-aws-check-123-eu-west-1-hub/unknown", + provider="aws", + severity="critical", + check_id="iam_root_mfa", + ) == [ + "prowler", + "prowler-aws", + "prowler-critical", + "prowler-iam_root_mfa", + "prowler-finding-prowler-aws-check-123-eu-west-1-hub/unknown", + ] + + def test_build_jira_issue_labels_skips_empty_parts(self): + assert build_jira_issue_labels( + finding_uid="", provider="", severity="", check_id="" + ) == ["prowler"] + + def test_build_jira_issue_labels_sanitizes_metadata(self): + assert build_jira_issue_labels( + finding_uid=" uid\x00 with spaces ", + provider="aws cloud", + severity="high severity", + check_id="check id", + ) == [ + "prowler", + "prowler-aws_cloud", + "prowler-high_severity", + "prowler-check_id", + "prowler-finding-uid_with_spaces", + ] + + def test_build_jira_issue_labels_preserves_maximum_length_uid(self): + finding_uid = "u" * (Jira.LABEL_MAX_LENGTH - len(Jira.FINDING_LABEL_PREFIX) - 1) + finding_label = build_jira_issue_labels( + finding_uid=finding_uid, + provider="gcp", + severity="low", + check_id="check", + )[-1] + + assert finding_label == f"{Jira.FINDING_LABEL_PREFIX}-{finding_uid}" + assert len(finding_label) == Jira.LABEL_MAX_LENGTH + + def test_build_jira_issue_labels_distinguishes_long_uids(self): + common_prefix = "u" * 300 + first_uid = f"{common_prefix}-first" + second_uid = f"{common_prefix}-second" + + first_label = build_jira_issue_labels( + finding_uid=first_uid, + provider="gcp", + severity="low", + check_id="check", + )[-1] + second_label = build_jira_issue_labels( + finding_uid=second_uid, + provider="gcp", + severity="low", + check_id="check", + )[-1] + + assert first_label == Jira.build_finding_label(first_uid) + assert second_label == Jira.build_finding_label(second_uid) + assert first_label != second_label + assert len(first_label) == Jira.LABEL_MAX_LENGTH + assert len(second_label) == Jira.LABEL_MAX_LENGTH + + @override_settings(UI_BASE_URL="") + def test_build_jira_finding_url_without_base_url(self): + assert build_jira_finding_url("prowler-aws-check-1") == "" + + @override_settings(UI_BASE_URL="https://cloud.example.com") + def test_build_jira_finding_url_with_base_url(self): + assert build_jira_finding_url("prowler-aws-check-1") == ( + "https://cloud.example.com/findings?filter[uid]=prowler-aws-check-1" + ) + # uid characters that would break the query string are encoded + assert build_jira_finding_url("a/b c&d") == ( + "https://cloud.example.com/findings?filter[uid]=a%2Fb%20c%26d" + ) + assert build_jira_finding_url("") == "" + + @pytest.mark.django_db + def test_get_tenant_name(self, tenants_fixture): + tenant = tenants_fixture[0] + assert get_tenant_name(str(tenant.id)) == tenant.name + + @pytest.mark.django_db + def test_get_tenant_name_unknown_or_invalid(self): + assert get_tenant_name("00000000-0000-0000-0000-000000000000") == "" + assert get_tenant_name("not-a-uuid") == "" diff --git a/api/uv.lock b/api/uv.lock index 079bc91c8f..f412da19a6 100644 --- a/api/uv.lock +++ b/api/uv.lock @@ -4835,8 +4835,8 @@ wheels = [ [[package]] name = "prowler" -version = "5.40.0" -source = { git = "https://github.com/prowler-cloud/prowler.git?rev=master#b6e9967da6bebd6c7b8b237317a2a95e2e0c65bc" } +version = "5.41.0" +source = { git = "https://github.com/prowler-cloud/prowler.git?rev=master#f05a490cd74a2c0f11a5d66d8ce29d03fa5c64a2" } dependencies = [ { name = "alibabacloud-actiontrail20200706" }, { name = "alibabacloud-credentials" }, @@ -4928,9 +4928,12 @@ dependencies = [ { name = "stackit-iaas" }, { name = "stackit-objectstorage" }, { name = "stackit-resourcemanager" }, + { name = "stackit-ske" }, { name = "tabulate" }, + { name = "truststore" }, { name = "tzlocal" }, { name = "uuid6" }, + { name = "zstandard" }, ] [[package]] @@ -6117,6 +6120,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/9c/38a74d0f7a89b4320f6d2366fb660638bda8860daa08748b12c713d84381/stackit_resourcemanager-0.8.0-py3-none-any.whl", hash = "sha256:dd04bb8353d041a137c4dcba190beabded7acfaff1bc98b218fce20a99389ebc", size = 81288, upload-time = "2026-05-13T09:43:07.81Z" }, ] +[[package]] +name = "stackit-ske" +version = "1.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, + { name = "python-dateutil" }, + { name = "requests" }, + { name = "stackit-core" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/9e/df3ad585cb96d028354f4253568e9879d81bb9395d5ebfa268fa9350e2df/stackit_ske-1.12.0.tar.gz", hash = "sha256:62814279f3b7fb2387648f92d14453a8905ad60115c07579f2741ddb7d1fcc94", size = 37239, upload-time = "2026-06-30T11:18:49.39Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/00/37/dc54fb7185a2d4da37308322ea1a7b992312030b2e37262de4eb4003f5c7/stackit_ske-1.12.0-py3-none-any.whl", hash = "sha256:45bd8084d87f14f818b3d7e824450248c8784ed204ca1b2dc108f491dcbdb1a3", size = 93142, upload-time = "2026-06-30T11:18:48.233Z" }, +] + [[package]] name = "statsd" version = "4.0.1" @@ -6225,6 +6243,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d0/30/dc54f88dd4a2b5dc8a0279bdd7270e735851848b762aeb1c1184ed1f6b14/tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2", size = 78540, upload-time = "2024-11-24T20:12:19.698Z" }, ] +[[package]] +name = "truststore" +version = "0.10.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/53/a3/1585216310e344e8102c22482f6060c7a6ea0322b63e026372e6dcefcfd6/truststore-0.10.4.tar.gz", hash = "sha256:9d91bd436463ad5e4ee4aba766628dd6cd7010cf3e2461756b3303710eebc301", size = 26169, upload-time = "2025-08-12T18:49:02.73Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/19/97/56608b2249fe206a67cd573bc93cd9896e1efb9e98bce9c163bcdc704b88/truststore-0.10.4-py3-none-any.whl", hash = "sha256:adaeaecf1cbb5f4de3b1959b42d41f6fab57b2b1666adb59e89cb0b53361d981", size = 18660, upload-time = "2025-08-12T18:49:01.46Z" }, +] + [[package]] name = "typer" version = "0.21.1" @@ -6621,6 +6648,48 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/81/2f171fbc4222066957e6b9220c4fb9146792540102c37e6d94e5d14aad97/zope_interface-8.2-cp312-cp312-win_amd64.whl", hash = "sha256:845d14e580220ae4544bd4d7eb800f0b6034fe5585fc2536806e0a26c2ee6640", size = 212444, upload-time = "2026-01-09T08:05:25.148Z" }, ] +[[package]] +name = "zstandard" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fd/aa/3e0508d5a5dd96529cdc5a97011299056e14c6505b678fd58938792794b1/zstandard-0.25.0.tar.gz", hash = "sha256:7713e1179d162cf5c7906da876ec2ccb9c3a9dcbdffef0cc7f70c3667a205f0b", size = 711513, upload-time = "2025-09-14T22:15:54.002Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2a/83/c3ca27c363d104980f1c9cee1101cc8ba724ac8c28a033ede6aab89585b1/zstandard-0.25.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:933b65d7680ea337180733cf9e87293cc5500cc0eb3fc8769f4d3c88d724ec5c", size = 795254, upload-time = "2025-09-14T22:16:26.137Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4d/e66465c5411a7cf4866aeadc7d108081d8ceba9bc7abe6b14aa21c671ec3/zstandard-0.25.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3f79487c687b1fc69f19e487cd949bf3aae653d181dfb5fde3bf6d18894706f", size = 640559, upload-time = "2025-09-14T22:16:27.973Z" }, + { url = "https://files.pythonhosted.org/packages/12/56/354fe655905f290d3b147b33fe946b0f27e791e4b50a5f004c802cb3eb7b/zstandard-0.25.0-cp311-cp311-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:0bbc9a0c65ce0eea3c34a691e3c4b6889f5f3909ba4822ab385fab9057099431", size = 5348020, upload-time = "2025-09-14T22:16:29.523Z" }, + { url = "https://files.pythonhosted.org/packages/3b/13/2b7ed68bd85e69a2069bcc72141d378f22cae5a0f3b353a2c8f50ef30c1b/zstandard-0.25.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:01582723b3ccd6939ab7b3a78622c573799d5d8737b534b86d0e06ac18dbde4a", size = 5058126, upload-time = "2025-09-14T22:16:31.811Z" }, + { url = "https://files.pythonhosted.org/packages/c9/dd/fdaf0674f4b10d92cb120ccff58bbb6626bf8368f00ebfd2a41ba4a0dc99/zstandard-0.25.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5f1ad7bf88535edcf30038f6919abe087f606f62c00a87d7e33e7fc57cb69fcc", size = 5405390, upload-time = "2025-09-14T22:16:33.486Z" }, + { url = "https://files.pythonhosted.org/packages/0f/67/354d1555575bc2490435f90d67ca4dd65238ff2f119f30f72d5cde09c2ad/zstandard-0.25.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:06acb75eebeedb77b69048031282737717a63e71e4ae3f77cc0c3b9508320df6", size = 5452914, upload-time = "2025-09-14T22:16:35.277Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1f/e9cfd801a3f9190bf3e759c422bbfd2247db9d7f3d54a56ecde70137791a/zstandard-0.25.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9300d02ea7c6506f00e627e287e0492a5eb0371ec1670ae852fefffa6164b072", size = 5559635, upload-time = "2025-09-14T22:16:37.141Z" }, + { url = "https://files.pythonhosted.org/packages/21/88/5ba550f797ca953a52d708c8e4f380959e7e3280af029e38fbf47b55916e/zstandard-0.25.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfd06b1c5584b657a2892a6014c2f4c20e0db0208c159148fa78c65f7e0b0277", size = 5048277, upload-time = "2025-09-14T22:16:38.807Z" }, + { url = "https://files.pythonhosted.org/packages/46/c0/ca3e533b4fa03112facbe7fbe7779cb1ebec215688e5df576fe5429172e0/zstandard-0.25.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f373da2c1757bb7f1acaf09369cdc1d51d84131e50d5fa9863982fd626466313", size = 5574377, upload-time = "2025-09-14T22:16:40.523Z" }, + { url = "https://files.pythonhosted.org/packages/12/9b/3fb626390113f272abd0799fd677ea33d5fc3ec185e62e6be534493c4b60/zstandard-0.25.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6c0e5a65158a7946e7a7affa6418878ef97ab66636f13353b8502d7ea03c8097", size = 4961493, upload-time = "2025-09-14T22:16:43.3Z" }, + { url = "https://files.pythonhosted.org/packages/cb/d3/23094a6b6a4b1343b27ae68249daa17ae0651fcfec9ed4de09d14b940285/zstandard-0.25.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c8e167d5adf59476fa3e37bee730890e389410c354771a62e3c076c86f9f7778", size = 5269018, upload-time = "2025-09-14T22:16:45.292Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a7/bb5a0c1c0f3f4b5e9d5b55198e39de91e04ba7c205cc46fcb0f95f0383c1/zstandard-0.25.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:98750a309eb2f020da61e727de7d7ba3c57c97cf6213f6f6277bb7fb42a8e065", size = 5443672, upload-time = "2025-09-14T22:16:47.076Z" }, + { url = "https://files.pythonhosted.org/packages/27/22/503347aa08d073993f25109c36c8d9f029c7d5949198050962cb568dfa5e/zstandard-0.25.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:22a086cff1b6ceca18a8dd6096ec631e430e93a8e70a9ca5efa7561a00f826fa", size = 5822753, upload-time = "2025-09-14T22:16:49.316Z" }, + { url = "https://files.pythonhosted.org/packages/e2/be/94267dc6ee64f0f8ba2b2ae7c7a2df934a816baaa7291db9e1aa77394c3c/zstandard-0.25.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72d35d7aa0bba323965da807a462b0966c91608ef3a48ba761678cb20ce5d8b7", size = 5366047, upload-time = "2025-09-14T22:16:51.328Z" }, + { url = "https://files.pythonhosted.org/packages/7b/a3/732893eab0a3a7aecff8b99052fecf9f605cf0fb5fb6d0290e36beee47a4/zstandard-0.25.0-cp311-cp311-win32.whl", hash = "sha256:f5aeea11ded7320a84dcdd62a3d95b5186834224a9e55b92ccae35d21a8b63d4", size = 436484, upload-time = "2025-09-14T22:16:55.005Z" }, + { url = "https://files.pythonhosted.org/packages/43/a3/c6155f5c1cce691cb80dfd38627046e50af3ee9ddc5d0b45b9b063bfb8c9/zstandard-0.25.0-cp311-cp311-win_amd64.whl", hash = "sha256:daab68faadb847063d0c56f361a289c4f268706b598afbf9ad113cbe5c38b6b2", size = 506183, upload-time = "2025-09-14T22:16:52.753Z" }, + { url = "https://files.pythonhosted.org/packages/8c/3e/8945ab86a0820cc0e0cdbf38086a92868a9172020fdab8a03ac19662b0e5/zstandard-0.25.0-cp311-cp311-win_arm64.whl", hash = "sha256:22a06c5df3751bb7dc67406f5374734ccee8ed37fc5981bf1ad7041831fa1137", size = 462533, upload-time = "2025-09-14T22:16:53.878Z" }, + { url = "https://files.pythonhosted.org/packages/82/fc/f26eb6ef91ae723a03e16eddb198abcfce2bc5a42e224d44cc8b6765e57e/zstandard-0.25.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b3c3a3ab9daa3eed242d6ecceead93aebbb8f5f84318d82cee643e019c4b73b", size = 795738, upload-time = "2025-09-14T22:16:56.237Z" }, + { url = "https://files.pythonhosted.org/packages/aa/1c/d920d64b22f8dd028a8b90e2d756e431a5d86194caa78e3819c7bf53b4b3/zstandard-0.25.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:913cbd31a400febff93b564a23e17c3ed2d56c064006f54efec210d586171c00", size = 640436, upload-time = "2025-09-14T22:16:57.774Z" }, + { url = "https://files.pythonhosted.org/packages/53/6c/288c3f0bd9fcfe9ca41e2c2fbfd17b2097f6af57b62a81161941f09afa76/zstandard-0.25.0-cp312-cp312-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:011d388c76b11a0c165374ce660ce2c8efa8e5d87f34996aa80f9c0816698b64", size = 5343019, upload-time = "2025-09-14T22:16:59.302Z" }, + { url = "https://files.pythonhosted.org/packages/1e/15/efef5a2f204a64bdb5571e6161d49f7ef0fffdbca953a615efbec045f60f/zstandard-0.25.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6dffecc361d079bb48d7caef5d673c88c8988d3d33fb74ab95b7ee6da42652ea", size = 5063012, upload-time = "2025-09-14T22:17:01.156Z" }, + { url = "https://files.pythonhosted.org/packages/b7/37/a6ce629ffdb43959e92e87ebdaeebb5ac81c944b6a75c9c47e300f85abdf/zstandard-0.25.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:7149623bba7fdf7e7f24312953bcf73cae103db8cae49f8154dd1eadc8a29ecb", size = 5394148, upload-time = "2025-09-14T22:17:03.091Z" }, + { url = "https://files.pythonhosted.org/packages/e3/79/2bf870b3abeb5c070fe2d670a5a8d1057a8270f125ef7676d29ea900f496/zstandard-0.25.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:6a573a35693e03cf1d67799fd01b50ff578515a8aeadd4595d2a7fa9f3ec002a", size = 5451652, upload-time = "2025-09-14T22:17:04.979Z" }, + { url = "https://files.pythonhosted.org/packages/53/60/7be26e610767316c028a2cbedb9a3beabdbe33e2182c373f71a1c0b88f36/zstandard-0.25.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5a56ba0db2d244117ed744dfa8f6f5b366e14148e00de44723413b2f3938a902", size = 5546993, upload-time = "2025-09-14T22:17:06.781Z" }, + { url = "https://files.pythonhosted.org/packages/85/c7/3483ad9ff0662623f3648479b0380d2de5510abf00990468c286c6b04017/zstandard-0.25.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:10ef2a79ab8e2974e2075fb984e5b9806c64134810fac21576f0668e7ea19f8f", size = 5046806, upload-time = "2025-09-14T22:17:08.415Z" }, + { url = "https://files.pythonhosted.org/packages/08/b3/206883dd25b8d1591a1caa44b54c2aad84badccf2f1de9e2d60a446f9a25/zstandard-0.25.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aaf21ba8fb76d102b696781bddaa0954b782536446083ae3fdaa6f16b25a1c4b", size = 5576659, upload-time = "2025-09-14T22:17:10.164Z" }, + { url = "https://files.pythonhosted.org/packages/9d/31/76c0779101453e6c117b0ff22565865c54f48f8bd807df2b00c2c404b8e0/zstandard-0.25.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1869da9571d5e94a85a5e8d57e4e8807b175c9e4a6294e3b66fa4efb074d90f6", size = 4953933, upload-time = "2025-09-14T22:17:11.857Z" }, + { url = "https://files.pythonhosted.org/packages/18/e1/97680c664a1bf9a247a280a053d98e251424af51f1b196c6d52f117c9720/zstandard-0.25.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:809c5bcb2c67cd0ed81e9229d227d4ca28f82d0f778fc5fea624a9def3963f91", size = 5268008, upload-time = "2025-09-14T22:17:13.627Z" }, + { url = "https://files.pythonhosted.org/packages/1e/73/316e4010de585ac798e154e88fd81bb16afc5c5cb1a72eeb16dd37e8024a/zstandard-0.25.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f27662e4f7dbf9f9c12391cb37b4c4c3cb90ffbd3b1fb9284dadbbb8935fa708", size = 5433517, upload-time = "2025-09-14T22:17:16.103Z" }, + { url = "https://files.pythonhosted.org/packages/5b/60/dd0f8cfa8129c5a0ce3ea6b7f70be5b33d2618013a161e1ff26c2b39787c/zstandard-0.25.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:99c0c846e6e61718715a3c9437ccc625de26593fea60189567f0118dc9db7512", size = 5814292, upload-time = "2025-09-14T22:17:17.827Z" }, + { url = "https://files.pythonhosted.org/packages/fc/5f/75aafd4b9d11b5407b641b8e41a57864097663699f23e9ad4dbb91dc6bfe/zstandard-0.25.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:474d2596a2dbc241a556e965fb76002c1ce655445e4e3bf38e5477d413165ffa", size = 5360237, upload-time = "2025-09-14T22:17:19.954Z" }, + { url = "https://files.pythonhosted.org/packages/ff/8d/0309daffea4fcac7981021dbf21cdb2e3427a9e76bafbcdbdf5392ff99a4/zstandard-0.25.0-cp312-cp312-win32.whl", hash = "sha256:23ebc8f17a03133b4426bcc04aabd68f8236eb78c3760f12783385171b0fd8bd", size = 436922, upload-time = "2025-09-14T22:17:24.398Z" }, + { url = "https://files.pythonhosted.org/packages/79/3b/fa54d9015f945330510cb5d0b0501e8253c127cca7ebe8ba46a965df18c5/zstandard-0.25.0-cp312-cp312-win_amd64.whl", hash = "sha256:ffef5a74088f1e09947aecf91011136665152e0b4b359c42be3373897fb39b01", size = 506276, upload-time = "2025-09-14T22:17:21.429Z" }, + { url = "https://files.pythonhosted.org/packages/ea/6b/8b51697e5319b1f9ac71087b0af9a40d8a6288ff8025c36486e0c12abcc4/zstandard-0.25.0-cp312-cp312-win_arm64.whl", hash = "sha256:181eb40e0b6a29b3cd2849f825e0fa34397f649170673d385f3598ae17cca2e9", size = 462679, upload-time = "2025-09-14T22:17:23.147Z" }, +] + [[package]] name = "zstd" version = "1.5.7.2" diff --git a/docs/user-guide/tutorials/prowler-app-jira-integration.mdx b/docs/user-guide/tutorials/prowler-app-jira-integration.mdx index 27832352f5..bc9fdeb504 100644 --- a/docs/user-guide/tutorials/prowler-app-jira-integration.mdx +++ b/docs/user-guide/tutorials/prowler-app-jira-integration.mdx @@ -124,6 +124,18 @@ To manually send individual Findings to Jira: ![Send to Jira modal](/images/prowler-app/jira/send-to-jira-modal.png) +### Finding Reference in the Jira Issue + + + +Every Jira issue created from a single Finding carries a stable reference back to that Finding, so issues can be filtered, searched with Jira Query Language (JQL), or matched by automation: + +* **Labels**: `prowler`, `prowler-`, `prowler-`, `prowler-` and `prowler-finding-`. Labels are sanitized deterministically: whitespace becomes `_`, control characters are removed, and values are truncated to Jira's 255-character label limit. +* **Finding URL**: a link that opens the Finding in Prowler, filtered by its unique identifier (UID) so it keeps working after later scans. +* **Tenant Info**: the name of the Prowler organization that sent the Finding. + +Prowler Cloud always includes the Finding URL. In Prowler Local Server, set `DJANGO_UI_BASE_URL` in the API environment (for example, `https://prowler.example.com`) to enable it. When the variable is empty, the issue is created without the link. + ## Integration Status Monitor and manage your Jira integrations through the management interface: From 6422178b76da904b1ecdeb30171050a686e328a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Mon, 31 Aug 2026 18:13:30 +0200 Subject: [PATCH 10/77] feat(sdk): AWS partition selection via PROWLER_AWS_PARTITION (#12680) Co-authored-by: David --- .../aws-partition-env-var.added.md | 1 + prowler/providers/aws/aws_provider.py | 134 ++++++++- tests/providers/aws/aws_provider_test.py | 256 ++++++++++++++++++ 3 files changed, 380 insertions(+), 11 deletions(-) create mode 100644 prowler/changelog.d/aws-partition-env-var.added.md diff --git a/prowler/changelog.d/aws-partition-env-var.added.md b/prowler/changelog.d/aws-partition-env-var.added.md new file mode 100644 index 0000000000..c94ed6b23d --- /dev/null +++ b/prowler/changelog.d/aws-partition-env-var.added.md @@ -0,0 +1 @@ +`PROWLER_AWS_PARTITION` environment variable to select the AWS partition used for STS credential validation and scan bootstrap, with a clear error when the account belongs to a different partition diff --git a/prowler/providers/aws/aws_provider.py b/prowler/providers/aws/aws_provider.py index b4c9ed3771..d6b24c748c 100644 --- a/prowler/providers/aws/aws_provider.py +++ b/prowler/providers/aws/aws_provider.py @@ -1,6 +1,7 @@ import os import pathlib from datetime import datetime +from functools import lru_cache from re import fullmatch from typing import Optional @@ -671,7 +672,12 @@ class AwsProvider(Provider): if mfa: session = Session(**session_arguments) session._session.set_default_client_config(session_config) - sts_client = session.client("sts") + sts_region = ( + get_env_partition_bootstrap_region() + or session.region_name + or AWS_STS_GLOBAL_ENDPOINT_REGION + ) + sts_client = AwsProvider.create_sts_session(session, sts_region) # TODO: pass values from the input mfa_info = AwsProvider.input_role_mfa_token_and_code() @@ -1352,7 +1358,7 @@ class AwsProvider(Provider): @staticmethod def test_connection( profile: str = None, - aws_region: str = AWS_STS_GLOBAL_ENDPOINT_REGION, + aws_region: str = None, role_arn: str = None, role_session_name: str = ROLE_SESSION_NAME, session_duration: int = 3600, @@ -1369,7 +1375,9 @@ class AwsProvider(Provider): Args: profile (str): The AWS profile to use for the session. - aws_region (str): The AWS region to validate the credentials in. + aws_region (str): The AWS region to validate the credentials in. When not + provided, it defaults to the bootstrap region of the partition set in + the PROWLER_AWS_PARTITION environment variable or, if unset, to us-east-1. role_arn (str): The ARN of the IAM role to assume. role_session_name (str): The name of the role session. session_duration (int): The duration of the assumed role session in seconds. @@ -1412,6 +1420,12 @@ class AwsProvider(Provider): Connection(is_connected=True, Error=None)) """ try: + if aws_region is None: + aws_region = ( + get_env_partition_bootstrap_region() + or AWS_STS_GLOBAL_ENDPOINT_REGION + ) + session = AwsProvider.setup_session( mfa=mfa_enabled, profile=profile, @@ -1430,6 +1444,7 @@ class AwsProvider(Provider): external_id=external_id, mfa_enabled=mfa_enabled, role_session_name=role_session_name, + sts_region=aws_region, ) assumed_role_credentials = AwsProvider.assume_role( session, @@ -1451,6 +1466,13 @@ class AwsProvider(Provider): if provider_id and caller_identity.account != provider_id: raise AWSInvalidProviderIdError(file=pathlib.Path(__file__).name) + # Validate that the account belongs to the configured partition, if any + env_partition = os.environ.get("PROWLER_AWS_PARTITION", "").strip() + if env_partition and caller_identity.arn.partition != env_partition: + raise AWSInvalidPartitionError( + message=f"The AWS account is in the {caller_identity.arn.partition} partition, but this deployment is configured for the {env_partition} partition via PROWLER_AWS_PARTITION" + ) + return Connection( is_connected=True, ) @@ -1591,6 +1613,14 @@ class AwsProvider(Provider): raise session_token_expired return Connection(error=session_token_expired) + except AWSInvalidPartitionError as invalid_partition_error: + logger.error( + f"{invalid_partition_error.__class__.__name__}[{invalid_partition_error.__traceback__.tb_lineno}]: {invalid_partition_error}" + ) + if raise_on_exception: + raise invalid_partition_error + return Connection(error=invalid_partition_error) + except Exception as error: logger.critical( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" @@ -1618,14 +1648,9 @@ class AwsProvider(Provider): sts_client = create_sts_session(session, 'us-west-2') """ try: - if os.environ.get("AWS_ENDPOINT_URL"): - sts_endpoint_url = os.environ["AWS_ENDPOINT_URL"] - elif aws_region.startswith("cn-"): - sts_endpoint_url = f"https://sts.{aws_region}.amazonaws.com.cn" - elif aws_region.startswith("eusc-"): - sts_endpoint_url = f"https://sts.{aws_region}.amazonaws.eu" - else: - sts_endpoint_url = f"https://sts.{aws_region}.amazonaws.com" + # Botocore resolves the regional STS endpoint for every partition + # (China, EUSC, GovCloud, ISO); AWS_ENDPOINT_URL overrides it + sts_endpoint_url = os.environ.get("AWS_ENDPOINT_URL") or None return session.client("sts", aws_region, endpoint_url=sts_endpoint_url) except Exception as error: logger.critical( @@ -1702,6 +1727,80 @@ def read_aws_regions_file() -> dict: return data +@lru_cache(maxsize=1) +def get_botocore_partition_regions() -> dict: + """ + Get the AWS partitions and their bootstrap region candidates from the + botocore endpoints data. + + The region of the partition's global STS endpoint, when declared, is moved + to the front since it is never an opt-in region; the rest are sorted + alphabetically. + + Returns: + dict: A dictionary mapping each partition name to its list of regions. + """ + endpoints_data = BotocoreSession().get_data("endpoints") + partition_regions = {} + for partition in endpoints_data["partitions"]: + regions = sorted(partition.get("regions", {})) + sts_service = partition.get("services", {}).get("sts", {}) + global_endpoint = sts_service.get("partitionEndpoint") + global_region = ( + sts_service.get("endpoints", {}) + .get(global_endpoint, {}) + .get("credentialScope", {}) + .get("region") + ) + if global_region in regions: + regions.remove(global_region) + regions.insert(0, global_region) + partition_regions[partition["partition"]] = regions + return partition_regions + + +def get_env_partition_regions() -> Optional[list]: + """ + Get the bootstrap region candidates for the partition set in the + PROWLER_AWS_PARTITION environment variable. + + Returns: + Optional[list]: The regions of the configured partition, preferred + bootstrap region first, or None when the environment variable is + not set. + + Raises: + AWSInvalidPartitionError: If the value is not a partition known to botocore. + """ + raw_partition = os.environ.get("PROWLER_AWS_PARTITION", "").strip() + if not raw_partition: + return None + + partition_regions = get_botocore_partition_regions() + regions = partition_regions.get(raw_partition) + if not regions: + raise AWSInvalidPartitionError( + message=f"Invalid partition: {raw_partition} set in PROWLER_AWS_PARTITION. Valid partitions: {', '.join(sorted(partition_regions))}" + ) + return regions + + +def get_env_partition_bootstrap_region() -> Optional[str]: + """ + Get the STS bootstrap region for the partition set in the + PROWLER_AWS_PARTITION environment variable. + + Returns: + Optional[str]: The preferred bootstrap region of the configured + partition, or None when the environment variable is not set. + + Raises: + AWSInvalidPartitionError: If the value is not a partition known to botocore. + """ + regions = get_env_partition_regions() + return regions[0] if regions else None + + # TODO: This can be moved to another class since it doesn't need self def get_aws_region_for_sts( session_region: str, @@ -1711,6 +1810,10 @@ def get_aws_region_for_sts( """ Get the AWS region for the STS Assume Role operation. + The precedence is: explicit regions, the partition set in the + PROWLER_AWS_PARTITION environment variable, the session region and, + finally, the bootstrap region candidates. + Args: - session_region (str): The region configured in the AWS session. - regions (set[str]): The regions passed with the -f/--region/--filter-region option. @@ -1730,6 +1833,15 @@ def get_aws_region_for_sts( if region not in excluded_regions: return region + env_partition_regions = get_env_partition_regions() + if env_partition_regions: + # The configured partition constrains the whole fallback chain: prefer + # a non-excluded region, but never leave the partition + for region in env_partition_regions: + if region not in excluded_regions: + return region + return env_partition_regions[0] + if session_region and session_region not in excluded_regions: return session_region diff --git a/tests/providers/aws/aws_provider_test.py b/tests/providers/aws/aws_provider_test.py index f874ca8812..4bdb438b99 100644 --- a/tests/providers/aws/aws_provider_test.py +++ b/tests/providers/aws/aws_provider_test.py @@ -1783,6 +1783,29 @@ aws: assert sts_session._endpoint._endpoint_prefix == "sts" assert sts_session._endpoint.host == f"https://sts.{aws_region}.amazonaws.eu" + @mock_aws + def test_create_sts_session_empty_endpoint_url(self): + current_session = session.Session() + aws_region = AWS_REGION_US_EAST_1 + with mock.patch.dict(os.environ, {"AWS_ENDPOINT_URL": ""}): + sts_session = AwsProvider.create_sts_session(current_session, aws_region) + + assert sts_session._service_model.service_name == "sts" + assert sts_session._client_config.region_name == aws_region + assert sts_session._endpoint._endpoint_prefix == "sts" + assert sts_session._endpoint.host == f"https://sts.{aws_region}.amazonaws.com" + + @mock_aws + def test_create_sts_session_iso(self): + current_session = session.Session() + aws_region = "us-iso-east-1" + sts_session = AwsProvider.create_sts_session(current_session, aws_region) + + assert sts_session._service_model.service_name == "sts" + assert sts_session._client_config.region_name == aws_region + assert sts_session._endpoint._endpoint_prefix == "sts" + assert sts_session._endpoint.host == f"https://sts.{aws_region}.c2s.ic.gov" + @mock_aws @patch( "prowler.lib.check.utils.recover_checks_from_provider", @@ -2219,6 +2242,239 @@ aws: == AWS_REGION_US_EAST_1 ) + def test_get_aws_region_for_sts_env_partition_gov_cloud(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ): + assert get_aws_region_for_sts(None, None) == AWS_REGION_GOV_CLOUD_US_EAST_1 + + def test_get_aws_region_for_sts_env_partition_china(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_CHINA_PARTITION}, + clear=False, + ): + assert get_aws_region_for_sts(None, None) == AWS_REGION_CN_NORTH_1 + + def test_get_aws_region_for_sts_env_partition_eusc(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_EUSC_PARTITION}, + clear=False, + ): + assert get_aws_region_for_sts(None, None) == AWS_REGION_EUSC_DE_EAST_1 + + def test_get_aws_region_for_sts_env_partition_iso(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_ISO_PARTITION}, + clear=False, + ): + assert get_aws_region_for_sts(None, None) == "us-iso-east-1" + + def test_get_aws_region_for_sts_env_partition_overrides_session_region(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ): + assert ( + get_aws_region_for_sts(AWS_REGION_EU_WEST_1, None) + == AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + def test_get_aws_region_for_sts_input_regions_take_precedence_over_env_partition( + self, + ): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ): + assert ( + get_aws_region_for_sts(None, {AWS_REGION_EU_WEST_1}) + == AWS_REGION_EU_WEST_1 + ) + + def test_get_aws_region_for_sts_env_partition_invalid_raises(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": "aws-invalid"}, + clear=False, + ): + with pytest.raises(AWSInvalidPartitionError): + get_aws_region_for_sts(None, None) + + @mock_aws + def test_test_connection_uses_env_partition_sts_region(self): + with ( + mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ), + mock.patch.object( + AwsProvider, + "validate_credentials", + return_value=AWSCallerIdentity( + user_id="test-user-id", + account=AWS_ACCOUNT_NUMBER, + arn=ARN(AWS_GOV_CLOUD_ACCOUNT_ARN), + region=AWS_REGION_GOV_CLOUD_US_EAST_1, + ), + ) as mock_validate_credentials, + ): + connection = AwsProvider.test_connection( + aws_access_key_id="test-access-key", + aws_secret_access_key="test-secret-key", + raise_on_exception=False, + ) + + assert connection.is_connected + assert ( + mock_validate_credentials.call_args.args[1] + == AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + @mock_aws + def test_test_connection_role_uses_env_partition_sts_region(self): + with ( + mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ), + mock.patch.object( + AwsProvider, + "assume_role", + return_value=AWSCredentials( + aws_access_key_id="assumed-access-key", + aws_secret_access_key="assumed-secret-key", + aws_session_token="assumed-session-token", + expiration=datetime.now(), + ), + ) as mock_assume_role, + mock.patch.object( + AwsProvider, + "validate_credentials", + return_value=AWSCallerIdentity( + user_id="test-user-id", + account=AWS_ACCOUNT_NUMBER, + arn=ARN(AWS_GOV_CLOUD_ACCOUNT_ARN), + region=AWS_REGION_GOV_CLOUD_US_EAST_1, + ), + ), + ): + connection = AwsProvider.test_connection( + role_arn=f"arn:{AWS_GOV_CLOUD_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:role/test-role", + aws_access_key_id="test-access-key", + aws_secret_access_key="test-secret-key", + raise_on_exception=False, + ) + + assert connection.is_connected + assumed_role_info = mock_assume_role.call_args.args[1] + assert assumed_role_info.sts_region == AWS_REGION_GOV_CLOUD_US_EAST_1 + + def test_get_aws_region_for_sts_env_partition_commercial(self): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_COMMERCIAL_PARTITION}, + clear=False, + ): + assert get_aws_region_for_sts(None, None) == AWS_REGION_US_EAST_1 + + def test_get_aws_region_for_sts_env_partition_excluded_region_stays_in_partition( + self, + ): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ): + assert ( + get_aws_region_for_sts(None, None, {AWS_REGION_GOV_CLOUD_US_EAST_1}) + == "us-gov-west-1" + ) + + def test_get_aws_region_for_sts_env_partition_all_regions_excluded_stays_in_partition( + self, + ): + with mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ): + assert ( + get_aws_region_for_sts( + None, None, {AWS_REGION_GOV_CLOUD_US_EAST_1, "us-gov-west-1"} + ) + == AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + @mock_aws + def test_setup_session_mfa_uses_env_partition_sts_region(self): + with ( + mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ), + mock.patch.object( + AwsProvider, + "input_role_mfa_token_and_code", + return_value=AWSMFAInfo( + arn=f"arn:{AWS_GOV_CLOUD_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:mfa/test", + totp="123456", + ), + ), + mock.patch.object( + AwsProvider, + "create_sts_session", + side_effect=AwsProvider.create_sts_session, + ) as mock_create_sts_session, + ): + AwsProvider.setup_session( + mfa=True, + aws_access_key_id="test-access-key", + aws_secret_access_key="test-secret-key", + ) + + assert ( + mock_create_sts_session.call_args.args[1] + == AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + @mock_aws + def test_test_connection_env_partition_mismatch(self): + with ( + mock.patch.dict( + os.environ, + {"PROWLER_AWS_PARTITION": AWS_GOV_CLOUD_PARTITION}, + clear=False, + ), + mock.patch.object( + AwsProvider, + "validate_credentials", + return_value=AWSCallerIdentity( + user_id="test-user-id", + account=AWS_ACCOUNT_NUMBER, + arn=ARN(AWS_ACCOUNT_ARN), + region=AWS_REGION_US_EAST_1, + ), + ), + ): + connection = AwsProvider.test_connection( + aws_access_key_id="test-access-key", + aws_secret_access_key="test-secret-key", + raise_on_exception=False, + ) + + assert not connection.is_connected + assert isinstance(connection.error, AWSInvalidPartitionError) + def test_get_profile_region_avoids_excluded_session_region(self): mocked_session = mock.Mock(region_name=AWS_REGION_EU_WEST_1) From ceb601028ed5f985181d75c371e95dde68ced9a3 Mon Sep 17 00:00:00 2001 From: "Pablo Fernandez Guerra (PFE)" <148432447+pfe-nazaries@users.noreply.github.com> Date: Mon, 31 Aug 2026 18:27:11 +0200 Subject: [PATCH 11/77] fix(ui): apply Slack integration design feedback (#12677) --- .../prowler-app/alerts/create-alert-modal.png | Bin 197991 -> 198139 bytes .../prowler-app/alerts/edit-alert-test.png | Bin 189884 -> 191456 bytes .../prowler-app/slack/channel-picker.png | Bin 123059 -> 122935 bytes .../prowler-app/slack/connected-workspace.png | Bin 112258 -> 113939 bytes .../slack/disconnect-confirmation.png | Bin 159804 -> 159397 bytes .../slack/no-workspace-connected.png | Bin 94921 -> 95176 bytes .../prowler-app-slack-integration.mdx | 16 +- ui/__tests__/msw/handlers/slack.fixtures.ts | 4 +- .../(prowler)/alerts/alerts-page.harness.ts | 2 +- .../slack/slack-integration.harness.ts | 123 ++++++++-- .../slack/slack-page.integration.test.tsx | 104 ++++++-- .../slack-connection-check-result.added.md | 1 + .../slack-private-channel-marker.changed.md | 1 + ui/changelog.d/slack-ui-feedback.changed.md | 1 + .../shared/integration-card-header.tsx | 65 +++-- .../slack/slack-channel-multi-select.tsx | 39 ++- .../slack/slack-connection-check-status.tsx | 124 ++++++++++ .../integrations/slack/slack-inline-code.tsx | 15 ++ .../slack/slack-integration-card.tsx | 6 +- .../slack/slack-integration-manager.tsx | 230 ++++++++++++++---- ui/lib/external-urls.ts | 4 + ui/lib/integrations/slack-errors.ts | 4 +- ui/types/integrations.ts | 2 +- 23 files changed, 614 insertions(+), 127 deletions(-) create mode 100644 ui/changelog.d/slack-connection-check-result.added.md create mode 100644 ui/changelog.d/slack-private-channel-marker.changed.md create mode 100644 ui/changelog.d/slack-ui-feedback.changed.md create mode 100644 ui/components/integrations/slack/slack-connection-check-status.tsx create mode 100644 ui/components/integrations/slack/slack-inline-code.tsx diff --git a/docs/images/prowler-app/alerts/create-alert-modal.png b/docs/images/prowler-app/alerts/create-alert-modal.png index 57f7bd32c84bb04e3400aa225bb335d18986ad63..910c4b30d6f54ecf62ac0f30c170dcd78453c33e 100644 GIT binary patch literal 198139 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%0D8|XArgXM>%o9=G<+zuI}onjcM5! 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⪻Bjg&+M8E5;wJc9|05rYD^5bm7vB*3(C(oC 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 z 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

`k?w~U)@Rw1zp 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%0D>TXnX$ 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 Zhw$#1Clug(p9H@_sHtcxS1VeD{}0?pd{Y1b diff --git a/docs/images/prowler-app/alerts/edit-alert-test.png b/docs/images/prowler-app/alerts/edit-alert-test.png index ecbf038dd1cc517312c3020d56eb33471a9638fa..e36b86113ea657118a841c4f56027a92907f5715 100644 GIT binary patch literal 191456 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�XMZG_Ss8 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 P00000NkvXXu0mjfHg}&e literal 189884 zcmXtAWmuKL);)l!?tcM-&}2nj%tiGOYEQ_P6cCI&(BY_KIPnws2YIX7jzx+^RQKN-@F(EQ(7xPB~ zaS_P+lCm7uEs2u2^aLP{m(@O)LE^R(a~l<#hNr9-q7<{*rQMyut0^{8&etgSEWkWp zjIfL3>u{9p&+;N4K2G5qn_Ar0{|b72EV&Tiz_u?$lTj?xCVk>e^@xWD@@@YZlzTs> zcH;kM@4YGH_a~1Aq{t28ElrMO#}F^1>AJW088sf&I0-R@nEwnI^i{>0oXwBk%r((z zEIx`adH_>Cw_PxZ!*GC?-SpJXF9-?4*Z;?_Vcfe{Or@>gvYy@2Wdc?Z&jRsWV3(p8 zsmzMHmRVy7GjyFNJ7}<)W~N)DS+K>mn~Bs)m`Fb&MakCd9KwGyO$gm0&WD8-iel4RyO$A@LQXqx8Xnsv|=|u!cic%0tI79$|lzTj&)JMk+RMF1&f$ zA|6pU=Su4j4Y^IZg zSKXXnMZHYMpD4*O6En3ddFy29HY)_-kwBmgQ!S4QLL$zKo_-VXgBbcu6174uhLV0J zy$FZV2F|!RZd9)u5!=yk|G=vO!S^6gu>J?ZHU+QiH}4CCq_kIo@7r;mZ<&+nY(5{~ zZxGAI*cIT~lI-3da~&*sIqi{u;QYo8%mZ?z*!(_|XT+izS1&jWjZZWMk3izugwv+7 z2@go-GOC2I%-8AJO#kiU%RQp$yRyj%PZSr8W8~*Kl5@0#Q#VClmukvclV=9{s6NT1MvYCqB zi)rmyKwQO`8N>gyD2roDdFz)pTllbrG2fQu(ptT3O&aMXC`Ls;l5%UAK$ zyV+OZY`D7MfRF1D9xb@vxH2#w<_$pI(KBbJ2divF%vc*32bzrXmx{fmkcikQg&44_ z=Ce0nVSuXr4E9SV@11jmi17oEFe2=JoMC`VCa1aiStpdTG8{${UC#n}dE3HU(G%4_ z5PShHAiwRY6)F9~*9D9e$6}F@+-jw%R1Qh_4gB%Ab^xOD$Y?!h}PR#!U$@Car>ztVpVC zeMkf1IfgD~!OoC4Ba=IDI6HlH$Sr>0A0CWT9=#lRAQHs9d8ecDRkPQbr!5 zR9{b@VFwB1jBalLoBN*KbfAVjhfm%AI)v6ys0)<{g#1C+H%Y|H8Ro!p9>{=Ixrj?DBToKqY$)hM)8AXF zQ|!`{F0a-H3ZH!Xc9W)`BeZOdDGLFCE*9wp!&S3Z|40xM)k}<4&S&2xI*%AT4sGRb z5PMni&gZ_mR(E(2H&lcW{V=(!c()|76>O z1Cu9&ZsqY&CK_303xzixe8qq+3H~#tK{AN(Zzyz?bcn=G$N8I^QV0@^aBbYWOvpq1 z5rei(fOobWIL9alPv`2BF|?2LeTG4 znzFLGmX_!FR)16!rl@(dGcIn)>V8a&yjNRfB!;rGGBtIS`NCV3lT+GaznEaFBygr? zHg*jCL}BxM|7FMxs*-AquD%^L`)?_Y>R}HqHuy?X?9JGQhPjAU*JdCl0ioxImvigo zm^k~8buKUOxtc%Z-xUH$aVZzss~Hl})fSk>?wNZ;hM%;Ez6|QA*9+C5<76|(+kfyM z=k@H#c`=BrGThsi9IEuYs6|2p2akJ^icsY;k&eIxcOL z)Lf-{f+X2b`1+>O$@e-{Lg={JcMVjP`K*YhYofvRpmE7lma)9??iWd$lvrs76J*BF z1{%l6k9847{(8Kl184^i8`zEQBoQP)4B~uaaNJ)*xkqp$tCCAX`_1B5YjC~xyfYUg zl}X%}mEAOQDvmab=Yt>u-O!kpAkJCn_Mn4(Eicckisb!$DGLjYbS6vSpN;bJ)rhw+ zQa<;~*^>D5eM?lFJX+awHY+Hb1hgSQ5Dxn1fW=`#>;8*^yqcDlnu2s_`P0K#J&Ok> z<*W9Fo-GPV^x~2!j^wxm5wh^4@Nj8fvmu)-PpBpT+z1q0xMh>&4pq=3^LcJL_`cO7 zC(wK5dx(#ZhcUv!^|O$QwyJd-b3ok)w)D;C^E;gHjh}rnakJf^c+`TuPfJl8gve!+ z5p3=?y>sBxm`sw|Wv;IMm>DVZH-LlMf`fiRwqwSfe1E{L$!C82))tR6ep=L%3+qMI z_yEcNi2@vGRjaw1jLcO>yGMo8WKhg&K9{xMLqo+fY2MY7)G5&Rzau+ybISQNn#q|M z127oZg6wSz2z>v-g9bK*gBdNem~)k$9D%!wNQS*<9&Hq`zl>94>}MA zy3_g4twO9*@fx6_$|{R!9VX+?^b@HC#-X+&%q;sU(+*LRAS!Bd^3B3DYi_r#+Z=yn zclXvi)%>1hChde_BPxpI#6%8GPFCR!D4+B3{`1pAYa3#{R3JJUTJh@6XjNmLcG}R6 zeY^z9T_)N6h+RilibH_gM@^yAW6RZ1wHTp$Ba%g%{%jK2`TF6@VW^zR4GYBvOnAcH z21laW!SMMYLt)`Ke1Ji1x^X6J4{ z#LI;*gUZcYyMn20?BOQkj7#8167ewhegVw{8B+Q{4HLISoY1$sE0;{~IM@H#0=N3X z?}*epN_4fUQ?Z;%Wo&UqZE^;@JXai9O2NRYk_l4(!9mz-hT6|(TpN`hW83x1kgR^Z zVa)wE8QYojqd||so-_(+tl&YR-*nj15-jm5;{Uy>(|hM+mG@$DkJ&jkKEC2){{yA2 z_Z^~-k5T0+Y`JM?XNSePyZ`77lt~WBLl9jli<|1wf4;Xx*x|Xy*;P=J(=>qO@Zv+A zhUz{ArN0S!n!BK;osS99*X*n6$JH!C&I?}-3TkR&ArqQ+$-T;IOG~h8U!7{(&3uV? z0+^6T*p$TNg0>5Z#8^&F&I(mX0>t{k57C{|R#GmVD|T9?gJEyO@n(;_fM3(LN{^(F zf7xa!;s(t^B@%zx?O;sefQJfa{_nq(1v-h))affY2+1ez(YOq4)RvXUomW{#x9Ber zPFF9cc9N3n#S3(VPVvc9jKu`Z?oE{?Jp>^;geQdj;wml4&TmV! zIYU#l{(W8;PaBoR>ym^mq-|xTs=9Z)Q+#25-1SA%5t7f&LXJSg45rI|>jqCv{6U$6}cap6+c zuP7~cB5lENss5Ksic1P75C#1vkk=&N%@>}llvlR zh8T^GDOergPzQrCN%ce&m6Zu`iHXUwx@aR987V3xc z8U%?S&SQThtY^GOO-S+8>Y6$X+86^F>DtJP`R4Dec=6}q$N)!LL#rghw_9xtHJ53v zOszATsMltM7L(_`;4_BT(akwvS{SNRY|HXt<_NX1W>7bDz&%f_P^T06Cn%X@#RxKy zWHS5VX7CbgYJ`2-|IBC~%Ng+{Z8&&nXb8x!ULM~A57`5xV})2o&rCV#rD}gtD|$ll z0)+M4<|TD>zwR%^_4}JR<|Mhvk`FC!tVFB&bc+}9AC0qo-BzjdVor7y^Et5*j@zHi z?`@qCsdQO)S`f?fv|oCZ!b{S1{FG$#hF;93?dO0Ml_;@L3f+@!+~umvx{R`Tsfkup z(HcRuO44!N04CM8W4eQ${KvwpB_hEQvOlEsT1IjVz zn2a|AZ{Z?yk@Oy$Jk`lw$y6m@X#Qzih!xPjT4CI^Mu^ja{QGk#Be zI-;jzHJRrU9q z75c;dMf@m+jz!$0$vV+;{mmaZD@|!~L=}y8E^20pts&A-ulanu5yFh@u?5|ESZHWyczAd|ejNHDz{T~8<>~2( z@TcqdGYn3pEJhD+anqP}Nq#)FI`jHs%y8B}A3syf_YBfi<9PjxL|vQu3o3)0Hl50$ zJcbhyubTQf!ov4k?n<{_OI~&LLe-LbYPWBmg(g!cco#uAk`d=p5f>5>XsLWmM)+PV z!eAMc40dMA>p!;lW2rdI78-xb4-TUF-t$?|Y>QuZUeiz~)bDyY%KPC*qKRYfJxGVK zzH>9Iz8|wK(-<9-Zdg##lViit)m=Z|9+V>HNtu!n=koSMA_OxurNzeD9nMP3D6jak zItw8UmnS+0_RJup?qq4JDOgId6e^osT;*0n8k~v#yi-bzILhUCXQxa+n%XeYo|^p3 z)b*4y*TIpX;5!ekcRu{g@X4Uuz>Gpf3a>&gy;;wDS1gdsfrQ1aX6Uascm(atf4-6G ziC6mMc(`4L1u(8s(XQJ>2AAEIva0s?(AwJCn>7!)EV-gYR9qU%wcmF`v6QcEdU|^X zBM4_85ZjX#?g2t^2i9G2HPLn62j1boW4OkUd7?}_wdL=}y-f59Cj^zt!?qR}fYn{` zlPXtb|GFEIOmkRdQS+9iaOTy->66Qa$i&Z`Y@&@z?jggtknVS8N#l?z&XI~tCqJAd z(Whai!x&1grNYPw17ORP+(H3KPI4VYu=RcQIt?jFO({tNBAfqe( z#1eRnv3pG==)%#s|1NSC95oFS6Rpy)PEfB|C&hNVJ=;V?L`+)AqLoc`yqa5(H@JGI ztMyy0%XrOw8Ad4@p;u3oSlHNjy|Ps2(Xh#jL_%W}GZtqj)rwIuGC9e4^gOm7K=&Z} z>vfzuJq#@{8pJ5*)hIjv{FI()p~2_S$Op&F|NIwSs!V0oy^WfX$6@0A5gNP1q-f=e zRw_#c@(EmuOiFSV)beH0WGR95YR@4^DVx7{4;-%AnI z>ODUK1q@+YhJ6&$_?PLIs37D10OqY+;S2p0F4*KZC=|N2z1`c}dvth6fGzUv#<2CWz4F|tG?RuxElHC zDiJU`v#}+^zKW(q*v7@hNro}NQzk=9E3HBOuA zs(ad!^8DOhIl@ClfPEw3UTSnRgPL#VHV97RP42o<+?NUrSIY^!RC{F3of4vYc{mM$ zn-A}hQsok}v$OyFF>+^g-W^N1yV#2-XfKjG=QMe|J;$Y$rHXCM$ zCQZ@V>`i3UbI{P3%wVNiw;s@l-kh9I4U#_HZbu&-9RdF+1@4WBc~k0oxjzMb;Y-{m zO3Q@)VO>U{S{h+)`MFwe5j@ss(;wF)8pA>=D>>Mo;kOZiWC!;ik8y(_+1MKvn&eMd zL_gK248E}q&I%iB0flxf!0$Exd`PD2;Jhe0nRg!mp z?j>`iMri)z{Dy?YLAI#<*Vf)%GH^~K(rRjp`}J&hSi~Og?w1x4u4XniyczLNXOz*H zWXvl{zLlk=L}~mJ_H9$neNP{#M|RPDM@G=%q6tFZyhUgwE13g}$*U>!p$xX(uc!`~ zr(5vr^AM1$VRghdL=V;n$9=fhtiySuKE12`*>f?XQ=gLx!-6eUDwzrIt*LIZ-5SIs zeATuW!x1w#E?>P$tHplo7jp#D7kNFs4;cpH{VGQg)tni17nhr{6jn3F_E=u8`+CU& zjSf$4)gNeTc|Ha8X4b=)iYNK}b<-u2^n~@}8C!UNRKM^#PrdqX(P2SP7~=Ro=Ht$>MbN$> z-?Da>_3Hv7dieT+Pr|5}m}aJyU)szs_t{dUMQaxeq~1xS5OR1no23j5eY{_uhnlp8 z0p30UPfnhLfq@YrDDJY>?!hS`xIz_ULSAQ-9vk9~WqLvT9)LGM3`&#fj5YC9UPx9z zq#^UU>$k~r4XZ&%UCkoN=Lb)uiIHtLUZ1R5buT4Vsgsg(-RqHTogWJ#4YJm7Bjl{w zhOrKh6ciMYkdVa2#xgTACngT)N9uYHF^# zA5~ONFiBRa*X<^0TDNGq-d#)z6!ixLyef4CVlSmwR6uaB*!S;0zC{FxyBYRssMq!; z?6-ZMHwk(wbSJW+k|fg6*`k^`{poC@~JP{a-Fs6Tsr1CG}P;eQ1q`l#c9hP z=`<%$t6MsB&{u+J{dp+f2g`~3Ucu+fJOsQ7JNMd^FY)AMcx6D!>df%O_}i2F<402< z@f{o-y!(4`WpVm&9!;0^_Hb=Yr>GT&i}`> zs3XY)*2H~PN|f?R6t_m`tBf3Dj}L4_L|!dd#bxn%08w@3cy8zM?!wH>47f?ub^ZPQ z0Qh2Rws{o?!H)|!UMuCVbFQk_f&TTAPp{$)=ODjZqs6d>GBUev(g4O-afGuaUw9|UJc5B;^ST538?l4b$ifu;I-2ie zskuxg2JGdrqYmNPKVFr~tEv4;O&xhD+Ej`wN}_nn1gc*mMB(Pz+XuRq)^zv*xMC&m zUMHr>I+Jk&W2oTU?SaVk+ozk=)m5#Zm6c2>OfNtg^6s;aQ933q1vgRP%q%zvU5+^| z_Knn!%nZT#pI&8g*5FrL&nJ@x;u5ktPJ0;|1+zD!_0A3Q3w_pUM*s zEG-lJP&Fz}&Xh}}GqS~s3hYAJ{0WMHqGoLL=po~tmdvMIp~U;T3n5?ebfw!|dIdJj z@UQYLo5ru+eAVvLSu+Fc2}B3nL)<-qde9+p&Neww zZvDfRoAGZt(p$!2 z-!Z$DGd&Lk1I_zish5Ju>96f~l|W?fRB+h^50mqi1p189YDUxvba? zrm%u>aBzyHt*uX>4Hhj8K_`;{Vnn4pI5?>5G^gxweVoGU!h}~Cza5DFu30q!4-YTm zBb9*5zZR4e+{t1=*-J|Kb$+qDOGC>rn%!(vQe|oB9nHb=MUsaaiB7{m2bZ>$QvLqG z#J|N6=oF%y!-#Gj+0eEtXr-eJvkGxiRW((S6fi|4RZ~Aj?SrE=E$YS$0a-qE$9sp` z!G(slk|?wl-fxhvbJLNd_IiPlINpy{a(!%{7rAHQT*_E#&`LKQ=neo!RI7{r#&uLy zHgqZ~?=eyxjCLQh+2baDboH-)XjiM^$EBi=*GbRJ>~Om<>FsgE zi5)f~BqR)f_qlLpeyI)|iFVn|Vr2F5{1i_sm&sx*>Fv#rmlp=yMgo3Mu8cPlLu-`g zyAt#Jx>MrC{B;qkC6f%Dh#ut<3i2Z(6U|f-GeNwPwK1VU2wn`{uKXa|>Cx0eN5Q5+ z$AD@+o+4RaT?#K^QOB-kh>;r0^r@cL6hc9&MUpR6#{>|m>ES0_)24>s9?ZVkR%^*> zN|-HpH=G{(?rv#0NlDaaWp{Jpzyi$Ii=3=@lb?*z24 zq9|nEw>jf1!^6YxnEtThWoB|&PYR3)67;XyM?&__03JP>Ag^J#<$;UUP&Y8>OD-MA3w^-AnSxueSxJO2Yn*NoLoUk?5?k^ zKhtq)EvPFf`h3vTrue%sxvSo6OP&``f)d9MAjsUE?L9rhUJ$Ss;Q(CyTV-fOCpjLF zq_jF7&2@E^#e!2~FctO^3$iFAfAZ_Za0!}>egI*!`wB)0(yHrVOn+O`OEqAI~D{uEu zjEg@2D395_RSh_e((o2Ou3YlxbIx>McI>5%{lcn5#Vl^|>Lg*Wq{qwdR2e9EaPF|~ zG75nC+5KcBl;!=*aZW`H#<~B*p^*F|>Z=jjK4(*$JX7Nok`ziV)6p%fk8iTn--Wza zXb}!Sj7wz5bk3j8ruM0HI>T+5A-(+xM`YdE^yM$6LRO?Lgw0=g3VG=b_f9q)P&pRK z?HL(KbGcuBp(HUn1G1=5dd-Tptn5TzXgnqfk7<2axKGdJi;nIapwHGYQ~j6@f>B+i zuo+KVN$fS~MBs)4#cRYwUdm<;Vmy0g{=BOl_EOVq@EErP|MRp;8v~`WQq0rCtM3=t zex~L=x;jR@50f~Sz%3MkY<5`u(Uttluh(C>; z?gyg8EErj0Qg$Yz;7(^n)FP&}Pw+B-TQGtK)}>9>~B<#|z-#%IHc?@(#6jLJmlk9gHNM0EVe6PHe@DZ86hm*w*{ z3HNl?X3Xg`5l{VyR~a}HPtxrp#TUv~xSsYzzFJIl#dAaOX|_{Uosb+@^SCZFFy$@Y_>qwdjWltWQY zSk@I{tf%|${pP@4ZqKKb>I1`{-*RI>Tgd>(b@ghBHtRKhgL<7eBto(E6cWUw+mW7< zA~DU{Bz}62hK^2Hv<-g)c4@RKB0-(q3ppE_%9{x)z?2J-3WAc zg4sXyBd4y`8GwjOBO*{m>#(74gyd5j@pAmTioc-k7Zb_=RDi=noI__s_36|7jGSA; zC>bsswEK`XSY>TT^Oq|3#OY!yl1wQlEq(l=6*U@i-c0sE@6w-3JJEL;y(VXGHcuwu zM~Ov!8lAYSNu#)_xrZhDrAMnQZUbC9w1zbOnd)I`Iwr5jhvm9iQn#Tz;M&5rI;<`8Oh0`i&7fUUo8%MsOHJE{)nbU#goEl z=wHkg{dZODh}iISoJOr8l<(iCfLY=1KlJ6b=z8t8MVdrtR-|$-ObE_B(&E&^n?ck) zu1zMIuG{<(Q&Pyh9z%tY=vPJhohh=($pzZ&?#2SjjaZnX3ss$tKO=m zu&`oY+~yFn-Taq)eK<}TC=?~fsNwOKNYaW1)CjL3 zqRA$N^xh*-Wd^B!$5lNmcQ$lkPP^QB?bN+|Ke8L-i(SoUbkB^^}ubIR#FEiQYdT8@$rf9Om{$MV!KM;_SG?ukg zA;B^`C7c?qKtNTcsp;(O?CIH4Ypgn=rfy|b;Y0|K^uzH*S`D7usDnofRe6UI+VcJB z>Bj*9ePxvzOz}V3*yoK+<1&k6Gn`=!3vu!t`uG@R@fm0JtQ ztR_9RTdr~z1`XpM%8y4tSWkNC@w~-zx%Qn0yQh=YTfq^XOeUooywB!mWqO+pQ_2EQ zrrz9A%2}<|TR*v2K%rEbs_*`@qYsRZGv0suuyHI%@B6ps*ypIJ8)@m|r2Ugf=~_2e zWc2x@BCkIRftr(gdU^nypfJCXN!Qy+#3&(4vcJ~S1?#B@FVIW5bSPwKvo}~SgTrfh zx&V-_EH_&5xtzSGB&uAUomEmuqAbxC5P({>Iep=o;$~s7?+b}#H5qF@EG;77CKUdPYMq946vno%k)GdZW=@T>q%fW zR@=l)WhEs66qAXIOQhg$fwH-in4+Sgvhog40wWx=V4ksOhY&T#5i}lM1o+0;odpEgkGWd=V9#PxCAdDFdbZX zEx{ldFEkyi`XpWrl4+>DKGAj>B#97oB&w%zc=nV+Y*vP3QxEp8QKfD1cXPUyOrIk&Gn-rt6bBiqoG{WO$1*v6G45+cQeZk?8R3@@F0{vCOGIf%=(_Kt>{h-tM-VT zWHyOjpgFM84%(#<^LgAcXPsshKtdh)DypDy1EwvR#Q%T+WfQL_=fU8Khl}dMt%_zk zs^iPaQd9_9^;t(C>v*A=1^;L2uSBf{MZ_Mh?L}#x%LS{n1Z<@DfB*rF9_#E>?r&9J zXFhV4l=!cCiy0~&*4E}>_`{1AScoX)K*${(8KV;0tWQOtJ;y;D^`;tS_5~5CF~jb4 zQ?H>2+wb5tEs2pZl<4w`ibl0jhih}NjKDs@4OlMC^{i>~`5e;C_i%k;@L%7{oLq53 z2T!EFJg&bCmDLBS;*(Jl^&;{@)U@7!A^PXcY(Wx}p*=b0>6P#s<_VHn-f&RtL)PuP zPRTb8!q^`KHJQd|P+p`+bp1U&PLtr-de6wbB2#oUaI^W$lT8YqP?Hm#2_#ahX?JVY zDJN93RJ9zwDF{y^pSJ(&asG|pfgV1O;ak&NSL;5bW%X&M5YNm$81ue(yOW+jpX3~% zGz1BV`_2b$*v8x+BXY@E86g@ktB(zH<*O=0hunx-+s|M6<4yJAAy(aYmUsoReZVd&P{K?yEWC^p2iXHT4-h8>;Gr%ARQ4+%`%0O z_w4S{69KfM?tcY(KIi8 zgC6S4cq7u91=?sXS!=#HNH{3=*5o1ozuXyUG#93pmay?jvERQ}v1QIuMNInV1-Wdd z(N2D%Z!tl?vAjtkl~-QQ658QN?ZW=fEK!HihJff=zqnZ-T&QnzpqjOCoD1{nzu!9z z{I_D=jl2RF0~W$Rktg;dPPQG|m%fI)%@(5iJlhx~E3-s!tAGcH$;F3*eW1xy#MQ{i z$kFW~dVN$#k+3zT5CV`#ZM-2pa3BHKLElD%*ufmdKq};ot-8vQ_5A-~ z0WrK8uhiRA;Lf?APfLt3Y_~ygu2P=K_;_HCcMkt^g|eJw@7B8oYS?_XHg-ra`9GEG z2ZCT!2$O17LBn>e>(Ib9(RNGo_e*f7MpM~V_3UO~GW!2wnd-NuC&!ERPO59}9yjr$ zSCPRkfRdd{)YlpJY6*M(>uXa8&d*z7(a2_WgO#lQ0Phn@a;BW$_m zc-`(@{Iq^J*v-NYyVZky8%K4|h7;KYb(P6~nch;Fu8UR2V5K^bi3G2fMPpMv{ zFSqHJl0#?lS&u1*PnaSv*Q#8dI9baam`}>PI}FEr`o7qO+UswUA1}D{Lq+l7$@>WD zNnwk!>X*zkYu*AIyYx|D&tb*``zqhPfqpy-g^6^Ih?ug~c@y#Foe*Wvpl(e_sWUsf z?xO)ap?shiX4{F0# z|2IDn$^&wc#;N;?Cts~z&y06UG_GRRz|$Xw-7H|Q?Pn9^lKsxO`Xd|NM4BfQZwkU7 z0+orA_#rgIug~ts7{{v$A@;;^`8!{6_V6SW<*@ zj!1bSawFGQGVS-R_YUB27wc|1O_ukt=VK%;zRSA7-@*S~KY=-fVh&t(7H>G7fRiWG zh8lGcb;E-R|0SV@2Q_Er5+97lOR;Ppz{)`XVL_U^;H&F_i0FWQ(SGKA(!^h$jQCm( zO54B1T@sW?k`|U(Bg*Gf-MBN&jy5iGfb9#9SE5qgE18BzYE&6nz6|}19_@4T71^B_ z5WRP7Xk>0Dny_5_b@_){Rdd<&838K;GSwXXP{$Th6TtURsR0Bn^1!yQ{3uQR8d|op z55TWc##p9RN?BKoVQyJ8`%QRXmsxZpRClrwx1IDk>pNvj)@_^X>XW8gh{e{v>SE)U zJ85Pn&D+;@bx~RH$$y)zZPEIf$>Fqg7|91SXA*Ff6zwY?PB;q>#~?^raW5&J%*I&y zMN%*Bzp&)?9FO(DYDA~1P0Zp+Wo5cwTpzcp>A}lWLAcF*hSS0F{Sl)Ve+7Oa*qbBm zzc=5O>@}E#Eh8S{-FM4E{Laz(17`5XqV)$fWRQ+OA{;av007!#XR`00^@{%2B>3Zr zmI9i6C6fV#ZB6=v!$XM|4fIAVDbcx2ikyr&6*{Ay2`mCkwRoECR-HOtG(=H*uZp5o zkPsDkY(>noK#YzA5hE7v=$uwVw|A5b^m$TJeTxx?@q^{cE}=*;JFd%W`}T*rRVQln zr{ipFOjOh#C1U}D2PY?$6&387{ey$F3=9!~%r5cLW$af?H2?Mfg2jUMYHK34-XZJn$1WIih7&}a&6Ko}iov?2(nHLTbR_x$B3bXyn1>s+qZ?e(;PaDWgfE{+=%kxQgxi15`7%g8?Vm92WTMK+Ww=_ zYM8`KH}H%S>at&Le&5Z99aXZ93pnhKl@rd4tEBLGOaw&|(_v%dOCFx}Mt}8OC~Yf} zO`AZ4prWD*33X#&T>ax2l)axXkYD~bb^gc&q!fMCO5bvpCMQpO`lS+@4@ZoFD$4jc z(C5De-5Y;EiA;b6eex4pUY(Ay^+N)=A~U51KxFC}2GlDdIO#FtY4Rekm|OAcTZ>v& z3-KZc1{NPg0v$p#8=Yqgd5Ke-^I5ox*9~-!M5)J{D#LLNBvmcwljV^RnLTY&kzk?c zoWEC}mJYf(E!E=E8|UW_56yeir>7M%onCIPmjSBXV%~F@@%cjch35N%KS1x^CSx(H zwA{^WwuqRT?$^>+tyFvSQL;bs{-?U|6_*B+B&fM0jp3$XzYF;$J(IclD)QrdVBs|I z^|-G%U1lyfvz##T-}J@Ho1ywkc4O3D+1*tA!@tWw%3uCHsg-kPOI+r+V7+t0tY z4rf;zBpM1v!1#FIi+SnnEXgc?o%9Od4tOW>PSx>I+!9)UklCin>}>b<&v4txZ-4Be zp&xlPa+xbjOLymDWKVydA8guS&SEG)&G2tE51&?N8e^0DAffwuliN2LWj)RxYX`Y;x@fVOhSrpr49EG=WC^uPwxlpbL)TZGwB zM~;{ELdLkvYoFWbqPF&nGx@KJPfO)^n>#CdVv=%lJ{J{Df69#OSzPMTEWJT&dP6Nl5zEO_3&Vsz&_{APdJuTy0%x0(=|zXsQT9PsE`);*h;`1v!ZVK7+d9n8iB z1~pUrz`(%9&D~Oc#xh#_^XJcdPf7Yj{-m)r`y<9n7ofp@xQ1C-SY2VEG(QIs^WWW4 zO6^o>*KEy9^3%fF3IPQAZ~J|!MG}*y^HUg}$FO#^bpR&W*k=H*Pc>f|L0`B^tO;+c5=xN(PDe}VhyPrH@5LKfl4 ztkse9;_}j5*~!NA52@WBPEVykPHb?%I%KHFzouK&mKoRbgZ@P&JWIWd2J}ukn#;aU zk>|?(2_@K^E7MK2O+}kMZb;3vnTOAoP4~wvH+yC?h3&xQ3CdEh13Q%IJWl#ZcvV(a z={A30<={C?-5CW>q#MtRfBW`LQeo@f>FDEA_rs~;y};+^Wy|4E;F${%dn%4*ljX_& z{$h7uu`81nPi6g2yUdsAsZNUeuCYDRJ zZqNie%AkUz5w@b;Gs~@5j z8o3jUC(16RqEsJy{hH+`7-|2u#96NEst}Umc#N|6qbFT!TJj_=#JPmxmo^?pwpoYH zBlECv?PR8OpJ`<6BC7f zL03nB8v%lFAuTN}x0V!Ls;OIkis&Rb><(4uoIMOA<`*>|f4% z9m8yOizB0QN9G*@MU~Z3qzSQmynLS4Das;HcIHc^=r#X-Mvj_>#@^irNK2p6_i9VJ zvm3A5Or=db-YA_4yybIAnh2oq+X}c9MKXDv7rT=JZl5%>N|elf zJYqR$WIhXK@p|AN{--k_=s8m~{EoaufTBoVyp_F`8)!I4HwkoBzD;^fAdIV}NK>ds zVO=@LW!P}J);s1r-LF>MnG2p&lhstb**jMc-)@u%E}c|tmKT2LkTAQXM!Y_x5O(OF z-BI32bGarEo%;a0Rg#qx6SLg)T%(BCnQBYF*ZI>rH^I6#Jp0B{kqG38Y=m2(L zT~%V<9HZ(WnGl8a-an1xk1Se;es5eJ9Ua}BJ4|E7Gck)SdH?Vjc+!X!R>Smb$zfMS zOia;WIF5QyE|X2m=?K=8hL?@tf1k^(`|%?LY=7YF&-$$j>3@4=3HhPdZwj&Ab2xS; zfd@6CBEi>Z?-$Ewt-ikM4+{$y81jGgH0U+%;MZo4)Sipf+6VJR22Vl;n+pTWzRjdu z$bkPQ=5%-bz_!=TnrID*I)v&V>{!I?tXy3FxV^ih?WfDJpfBz?^AD&jUh%b zaX4x~3EIW#G7ZI|pZCRF0MM@EZXof$_ujWx`6t)0wWtQIDL{LMX~(}2_HtHrPhDQV zkkXXXJ!Gh2Rmg$~Bi-PDfG@4t@1yyin-f0))z4)z`ig#-aE_YWc4UI<(Ku(a zuG0?tXtG1r;;;SdYv+L;rGQ{8lH5)}0JZCAZqPRr%j*L3KG;$9^Y@3H{CC;k-c8kE zqg7IKPq=;we2eIdY?utf0NHZpcjC8=&aFlQ`o3v)oWLU@A`F2++4Kz+zKcsmtBQ(} z-XQH}*HE_g8SrFE2Ce)gw5mSmYh}l7Du7(Q05wA7Jd@6EE(!`ioOSPqNPTY$snMkI zG&)apjp6@c0d_|fO*Ja10EAPIPy8yws_vgy=*dAcF9kHb8JVx5oM^PRxs^UdAe9XdV(@NOtgEy!zUC;7C+ z1J4le=zsNs)aFh0CJwFX{FWb|ARQ7&EhrKB{)YBW6~{%#uD333NKfn$%rzH6PuWP0 zaT;f$YUX+qBKIwcm;pVk#;!vZAu`H&@mYN1L+OH0P<%=Y6o;>?sYzcS-_h|Yx1=T(JILya8<0f9HX9pjjrzxw@w+-cE0AG57wfxI|uo9DlUbX_%%an@=bHc_$xOu-&; z-hN0apuF$@cslE_sJid%g8`z1(jg!%AR(=^NJ&XIh;(;J3`j|Lr_wFm43g3v(%s$6 zz|6b-J$~QwAD5RGoOAYBd+oLE`?E-$pn_i>ToQxBJv*`gGKvTXXrwuxRt*a+RGH%B z3vo6+MfbSc|1LXbP~NbqCF8udwszELIjP|7fIQt$UvgcF1kSC%wlmreQ|{4+<0O{=<~xVS1eHvs<;(5HxBDD zbp6$gO&iXR1m-H`tuWHrr}C@$rSb}t!;cIu_uqg=6bD*Z#Q)t33QBDS+tZ-VO>*oX zb|@&XP;kspat!+73V}+7mTNC}tKg;e`4%{ONHB;Yk2|{g59?z?lDk)5T-*ebsbv6V z*THQ0?A)Am(a?a7-MAbt1h&JVMokcv@WJ62xJl^TF$93BYj&1&sODzQ7CMTi`UwtG z({M|sbuOD}Izp7!)g@+1SBz$A{+csxN=`~jiin8NZE|r4JuiqmwoFDvpkn!;A`qwt2i9RC32e}}TTVmZ0iC~j zLd5z(R`&Ps@D?HHjm3Z1sJCB}GUF*~ayuaa>N8EvrZ)}A_+y~Ighj^FTv!<9Yq)Eom>l^-+ZU15m9DqR=-!K3eKJ?#<$n@ z6UfHK#yMN0BF)7IA`(L&M?Tv!9b@2j*3i}Uvb20M{a#jf|A%aX5-Tw-R2Kgh{Z(?}>SD9GxnFzgvh=Hz8#i+uZ(fMjyCuyr+rS*qsh z?2MU(Wur(r{!i7`Kq{|oyMJ(;0zm_DC+~vO6O8R~5Fq(oy?1}A;NF>cV9m8$&Ju7T z9tV7_ja!Gu#NaXk5t*iK!g8I zOw3%Sn28z4uHM)VeWm2_?*H$2htiy0T;5=?5NIntU@yd#mIaS$`q|dCQ9GXxjXelkXO4bG#)uPREA?ZSa6URgS)0yblw>= zp3nJaWYHC}CncWS3Kl?2U}^%7M5&EF)SJ9?q0W|ai&S>f%hT&6q$BWRa+15IhMSDX z>LnA?4^`T0ruA8U`OdB`UHdMuV%R{(4fqQjx4kZ1Wq`pZ-yX_2K1IIMF!t`}F)=Yn^f5lk#_x2ILUz)sgQAgP! zK>37yA62{qDf``kE8}DqW2P;8iSGEQd5xEo_C52_uAi+Ph(zHC3Qjvj?mg1*z{k@Q zDtnwD5=+A-JYK@#=*w4_%0UoQnB!2lAHh!Z*F3O%VmFNXlMxNZj}g>e2qCsdP{QNtE;QKy1K>|!eD4E z0gH=^7A&f?Lk_<0F_U?$NzE(Y{Q1*(P(%v{0(h{(sKlEZ8j>drEZ$AeWnthkkWN}# zTjw6g$$qdfGn0~%8USaC#t*qMaVPclZt^tr_#cebrfhc6{z%Kp(k25{>KW~l@+yeY zbm19&POeuv?i=v{y?Qt4};*?j$ZI=}0#9@@`~iwoW*PiA@V|CT+b=KBY$KW%y5@qgJ2SAKR6 zMS!G9@H$J>gI~`v*KQ%Ov%CA4F;A^7w!28F@VthQt@Z1uJ9Fk+=a{(pf`XSZ`b4iZ zeiLL>d)JCE_q^DWl#MFV*4HO`x;(rsP$TogoZHdUl# zdlx5p(v>(EqhDl!9Rg^0?evBx9y#mL8%oF7PKZCGYH5WwyPVzKsw89=CXw)uB{n=@ zoLK8NXJEj@z=-Z$*KvC)0XHs8O(A9Zr&>U9W5YEoa!LBhhFd+2DoTc;ATglu+nFf~A-RCSjJQo}r}f?*9JzSWY}Ik3~y9!DDfS z;kH)+f-Qn3dxV69dHInvcW-HF>nkgNR9Djqv9{*tH&s{1q4{(FdEk{IAvW!#-!$R7 z)}w%#Ql$8Pgv*N==C8w=UoDS*R5dp@-tjMz1+rsjhL7BQsPmT}!Bz{=JUC;@F+&l+ z9DOY-o$8B*HUD%=FA_AxQ&UpL#>PsXjAW0GrKF}}t=ZZ|?Y=c%&6x)q6O*Hx+j|WS z;@(PG{pE;7KXe?s;_An?b?KxplS9J8C)v6?JFCsj4~C!Gy-G|>jQyCA?)71bS^goY z*#?J%Oc8~Kg>h-OR8}fwkA{))M(jtef-|!K09bsmTWyMOotT)2f_Z{0Z>U#`K2}k& zC7a6@Si7Es^*QkoaIIA1FSTR)ji{)o=;*raApb>&PcO&H%T84_53oB8^a-vU@B+s< zP_l5E=&88g`QbgbJ@g+uH(SqHI4}TURHWvxlykMN9V$UkRGdu{0Q@nckEd*CPo zhz6GXf{MRzX7NU6YWn2tphJ|x-mkd1oo`NyA=d^pTjW8?lZ zmBL%Ilk=VD)>cms)Ta068w{sP{+w+Z*VfdL3%Hq${t!1|!6zVynJ7!0F9*I^AD_0` zTD611&eNTorY4W^yzo#$me#YOCNnNl(v-?d7fb&Zv^8Kat#CbR1?tQ)orV~f(zC5$ zupZaY_5TGp-2q_sGvRp$FRJfQ@yB-Xq9Atv+u!W?wBd{J< zWjWe)BA7ZllnOwbA;Ij(3ZAp=C%-RC8r6`?Mcjy_Wa& zH-UkzI>7(I_-8}I*qsu;!_b+JZ_A!^brc(qE;z1V($Uk6hx%&ywTOTJn1fBGsN&X8 zRpkdw_wUTPtgUTq)atfQ;`XosOLQW5jk=%jo3Xksr*-$hnq;KaY<&hQTEXotE?z9# z`c`sTUlRLHQL#F3*0f&0`dvI-X(Yp085z~;>hiJ4GI;2{&TyK)KGKxjS#z9=Jp3WH zxyP-KPoUfCa8pCp3UAELrr}|2ZE7mco2}R~=s-1i&uMl2yQnW@YKk!1^CT!3RK6WP z>~?+i!%z$oO@?$!-chCsk?lUWe z5>pA>?JeoMt_`X^e*a!#!Tri>C{6C9%;N}pGsWMTSkd`|IYB;&E1)7YS6%mRz!otA zoLjoOy*|Ifj72Cf8#}r5}FgL&0VlB2LCH{m~$hP?PAQ*4zz!9=JP00MS8IFgC2M-N`T--2F zTBH#q?MI_SK3A~_8Nae0bY?yqN*@$5kJR2?XB@vg8iXA|5kn}8VVUd|4GlXuQ1=vV z{Ii7?_~jmD>s2l7Vts6$Ed08|6?$XAo!j5vpI|h^junAyW20dFEv&Do*DVz?>NE3e zy>NVUP`}=JTw<@Q6SIc+-@Wu0f;gkMQEGZpKv%$$D7oUp#)aZjvF~VP=lv}`_7}?X z&3oDBy(rA}T!_FY^O+C1S1c}Wb}h@1Jy89>tIM)=;rb%5G*b8?ZLB9qn=ZE3`{a0S z_Vz;CruoLDL#qz4T{fu?fjS~9u7qzK`l?Cds_ah2kY2|mbW^soH)r}neP;R5n4Y_T zmJ}C`cx)K>g@ju3N+Ff7RJ#5IC<2O8yZ^RrqonbQfzq?lWIVzPf|!H;_>p}v@}&D`09BNVzbMJb59g6#3{94+xmA5H9VwqAdEQSYy* zJbb%}u}-O-!dqr|0e5y3Towy(p2Rbt-WEU7Q$QE}8r-$(Rp=|6fBnw24d zSa%#)KDs(Welb6ZF{bpsBq+^Ykk)4w5Lm?lkLpU>1#*6)CFbf}bXtyV9nwH}lPplk z!*>&x%&wBPZJ=kokn1yY*9FTNy4m7F8wZEo*x}m*+zR^>qi`4VJEC9bkcHOPqC`E& zR!!Z~76&I0tM^T~>vog(*+Qgw$A#{XmbeIVQr@!f!Lj+xcZmFIb>*$Cf&S_@FD6(o zj1C$HxoU9)PniSWeW$$i@V>2Dx?OSS;5OOkYY70~V$34O=+CHthBG3EWN&W-1hyw^ zj-H(-89_Q|OiDq|bLH5VgY~D`QTX7UQ`laU!M8up*!LO8yYkll25KKvKoycVQ%d;} z!Hz;{j3Oee205QC7e%L+c#YyFf1Jw{9UvYbTd#^FbHl8HRA?_lf&9|#h zI8BGWR(F={ioFpd*)rvgumfJbo4rg3bUP$BTjDA}M$7xa`AYbB1PJafVpZ$N=b?!? zF9FzNO%exrb_B_*Q4qQunYL7mt-gXlZX`cDoa!Ua=ZKIu(_J#M%Y69YewAK~KF zSudVXtl^BV>R#Pm2a?&|9k5((Hm?u1Cah=Ib2cgne7> zuRf9>eNgtazq8>HQpkrGd3i0wM&7OVvkB3$guS=!OYA3j7Oe}x;qNbL>m3I6z4xl&Hdh*QMA61(Gry@ z8B7y|eY~WkL{(@wS9^OrP)?C2uC(`6?A>{KTrbS!dF~hkHFb=PHi!7m#bVcL&)cIxbp#9o%}w{+cO2aL-jecG48tN0w}yLCLf;>; zm)B{@2E87Jn)mn`Z7d;oY&Dx)1TOnCH!}FoGS!z>3XzWTob}) zogH1`0bia}XWA|`N|)L&Jjs{8lv9@}XWnMMhAs)tjgOzzL0WR^+N_%f?{o@PT8}f; zJv_K0fy78(_+lpPkE0n57n7m+15CL4;edIz{omx;NAp^U@287u*ZnLiVk{Jar+TqZ zVGq#R!DrC=-8YP3?dMB%3JORERed6yQ_{?gSo+h3ac&%a??pJ$>v|W0{Ij^|-5+@f zTc}dlADk7xc}O$_Y4LtiS8R2&0*~#9wBK0r*cxm)yzBj@m_3{^^d{3I!a>RnB!qIn zjQQIBw9hi3wx&jjzBfHbId(c&h1=<@}P<&$I!Az}Y_UP>$8{}O1Mw3)w zR-))#HrSc#8*l5*Yx&hm?@rIygzmnbDr}`u*G#}x%)9V;v5#6yFYXNqdYGKVF!zLK zimZtp;h1Si-QQ?e=Hi)fbvB2_$&pR7wVYa%nJfK}k&$tzRM4`xf+At)EzZj(IXZVY zJ?9%r3VeQ>WGyD3WJ9tOra}*&2u_;OAoZk4ZA2ATS5y1UXZ8h%@Aa2%jjFGhb5?HF$T za&<6WR9r;7uy{Hv)BV}rSp3aF2PlpNrY}`kKjCGjCtq_)irTfFDI2^?YrPkfvA4Hd z&nR1GGb<(8s7S(0^J!+dyBn?JzxDaL`x*T_{i=VRi_yF5P!=b9*$ zl($xV@o^QE%UPdjQq2v=?%(%2fBpRHS3iQs#-8s!E3O!4$H3Co<5Yx&A!8y$x)ovl z-?3@)v1wSG2WHNlmppUJD~-pmFrlT(P8t!ThGY4%slNg^J~>s`8-89pw*=+3HoBp$ z^d`f}mb^>XgPAW&3KZ8y7j<)WHq;oAouU#iJZs}%z|^47AghGpD4+iPb^EL=hMKG* z?6c^SM6{X|slMC$2f5?j5&Yi!KZW>CD`)5YEd$mn)mZrI~x0eUzw7JIM3)t@VE4TF-fS44O5Qh<1>RaEwrcleZo#5$RXh zN4FbX04E#J3Y)Tq-C>gnDHVRq;B)csXLzl`MB+5H?;agJ`n~ZdOPIXbR1Y63Gs`H{ zkFh>V0T&6+Ec?^wPSf(}&6n#e=PGl<@laO%)d|zpciwtlUM%EhX(-lTj5Jq2iwY&a z*hoZ3NJx-A9`U?%d`mWvoG5K8xjmQp)+^6^Tus6UBK%j7lhq?)R8v$pON24Ic={t( z-yUsVA{-s~^f5Nm(c5I&oJVW;>|mnyd@@0YAB(ZXrf}zN4;VAG_YbEph|{cD@;}4uxpr$3zn5ke!xNHR|&)J zS6*GZXeL-eL-mclSImi)wknuj+O)|5k#GwwEwt9?Vd1;uwpKxtC&<X-3Fv511+q|&xpp*HJs#BsLszO#4|fr1v0e_N1Tq)TaETA_ zT{y{h_kgRrzH8>%zbz{(VbdgUDVs+a=_%ugC+!Wssw#!_EKktvjhirlU+(9fWAQG) z4(Dt=uNUXS?}j9<|sNzspOVB?l)JPxe^>A(B$DO zJoj8|sMuMGsUB*=jL);lm|=Q+TPKvQ`mT3!b=7q>=>je)N0k1|MS%MkOGFTrKp@dS~;nCfnM!s#Zky@|C1amiJne9kGpV?Y!}-? z^|G%Zv?Pbg`bgjNlBAh>hRnN#6GKT0%OYvr*(#4MLj|GKq`2q!&u@$KGiaVAGwZ9W zN-L4G#K2_pq<*e`(J8`W8;KWU6>E$MkNRIN;QPlkp>$ns<+JrFC>A!hB2zq$AgmKT z)4NM9!ZdhjD1s%GN9Zh7xVwwt=c^{S-b%{aqwvtsd{t0{*evt#7BHU0tYmlJJx|n! zn6Bn9N=y#g1Q_^|&+)_t?Ag=@cb-R${3OzMKiknqW>kDoT-k`u9#`@9p2*Y}I4zz= zUKzN#Jz$*92^_z+TPc+eNf$6CrFp=t-ROLVQ=J=2uaGOR2R+>c2N4HVGi{5a;=`L0 zg`K^uqiE6^^FCbuS{r&)Se`cIJsB<;5ptRc;n;8Ox*cRT^YhuX9@Js&%FCwod||-> zp8lmJHM_L5G&k4%TFTlgs$hGY5_vA#J(X;96=4m2k+%Dp^~AP+aBQKo#AA8WOlot) zNxrw->Fe+|KOEsj%jK8Wvc*$P_xncd+(a z8?G2|K(G&RnO>ohD7A7f5TRZHfF{Hj~Bl_5)&@9GYdzEUmR-P~dl6QbTj$X=Pni>0&eCob&oHjOh{}yol>^ ze30~OO~PaC41(k}{oDK{{_@kM#Qxn{L?J^oYLC$G#^T7jrpHfE>O-hjP<1PW^Bo}A zi4^v8F>N_!+4pD#iAol`a}76*I){2cwLL|(m1}vf5Q6Z$8SBy)vRhIHf6Jh&F#Y%Z z=H_!h*CoXE9dhRhzFwn-hFfqoyAnHyA-4xr(ACpSJQw=y z-q3mn>xUq(`sXg6=gn2(EP15ji`YPHtqPFq9iV}CO4bue;eJ>sndx@^3nb>{OV+bg ziM=7AA&ArbB~mm~_I_c+sbtLL-`Y})KG-G@H+8~^d$)EVEV5E_oFWmY@9gaC043G~ z>7gv_o;6rHqHITnbR8Bt>F>$7og9ZoGp`5X973*2r%SK4n#!kd5eksG4Cm_%ejCJo z_7ymgwt$>9BjXT|UzP-~Xo)D-P8c%1?&6WeXsMfixh!`U7pAn7P>`#Gg1nTjE_`Dv z8=js8L8j(=BOwsD=K-uLze*i)`C7HkrVp3s3G40U9|j8d+Z{;?NXWV9SoxCYfw7IM zj7)#4U=tBrgTr)0E3^8$&!>h80+w8}=Yoj6qhVqAoUqXCOe|>FW_q6^>QC@WJVds@ z0R@~$4u1tvX7iG8b5Gi~T#i*i;ldJJIpJe@w}(hXtwBHQZtqeilEw>2T*BP%Hi$sr zFVpeH>hCjKFK@A-Gh}m;9W|S;*ljIN96);C)#W?`Pnyj?FmSxccB*W#!aCGE{yzLN z>LYvzJ@exHd@MB;*>bYGlcube^09c*N%n4K7=kqE;F;|P*_yyvCk;t(vNu)t_ejdABtWvJ9FwOp3ah89v;N9TjCI zozA~evF!oFU)iBgPg~#p(r&tmUiLN0dfyWx`MW(%+;qcD*{o{d{`%D*tbRD0*V)N% z^vQ>eT6}(ZA6de~ZkFd0X#7{P1B&6k;8tRO0;WtKU!bpgQ^ccRRMF_w<$a0g^#Ham zN}w4CLDyiGsqIhg2lSTre+857H(j9*fp7*W`J)?q#Db>EJhsAdD7?4zBrM{Dgn-`^ zMl#1|)3|X-z&r1BlwJpFw)l@961BHS`S^(7HiR|52;NSb+1vys(tO3Sdg-YN$+{O+ zOz}nE^+XCD7s)#~$~o5*)=Pv>O;4r-p8jkg07a+(#j9EOrlzq+)wQ+T? zo!xJoxvNFHL4x`BcJC^xbE`2#fBm{}cD_Qan=0oGx~>0$UldCjZ*IcY%=;d%tUSvx zC-tg=-mU2qA2bCm*@ZqKWTBe8z9cK>p8G6orQ@uc>#Zgz^j<=Ia%w^f*ZR-X82;4M zlm{37qv2INI&KO$*>h>!O9+wAuxWj-Uo)XAW$oMZ9Xm4Bi_CBJ+G(iGiLF~RM)8P= zrFb4btjSvYQI+in!IOYDkoYmFN|_O3j7&j42+_0=gJA=#TdmmOU4D`}>9eGqM=rNC z=4?DE?l!BLY+}SJe^tD9vrvlFd_&~sn*Tbs@~^fj$KX@!ylTyKy=4!I-CMx@VZkvA z57j}<^;1re_Nt{7bUZIj=lpJb!Bg}(*A5tCB)zKMZDeEO3gkygZJ+0snMc8yyuRMI zB0SvLS5u#?dfdRoq(a|g6^m`UGsfKC_u=XQk1TnjLF$JP4m*JBzcw6$!gggO9(P9$ z*L&XJ_Ws&bpBuGy+&u$i>9eyl0O8#B=d+#-1KjD|?DNKuvLShzi$71DJ(~V_iir+B z9m^P~G z{sgM!CDsUzr;lbZdl#*l}Qc4NSPpn5?hG>7}zz-YCSB+PN=VD~L@rF;1q zMu!^fPbJy$V#Yb==1n(>y5D^p!7_OPreU81NVl2=j1~|f+YxO3`-ibu(_3Ji!SwX> zAF5U2**bYySy^f66ChBiKh^g^Y!+00Cx5NC;@uIffL0)+L~gON5hdtgUIQ zsWp1RYfW_dzBV0dIfI@S0OkS?Ys*PDfF0~~1V!>?Ch~g0FolJo^UXTS40|IZBLEZX zzBk1ZN~jB(wAj!2J}N4<8ugBW!2m@?eU#oa1vr=-#(i;sfC`7hiHL|O`F=ucRLSN) z0pjJvdvo(%KwMVH5D@hbl8m}eO-h;p1)AIIig_JQieD2QfF}Zc1kTPE@T()BMVc(G z%$AJIlS}9|0_OO)ZpS{0>NaCJ(f~!3GX-P~*pxz@H5myBJPs4TkD$m5W==3~VtIKP zz#2<*8kD|&)bYCD2I?I$o|5U(=TTnDO3FZgGKvO7QWX3yaqo>-h2OkMJ_TnJAi%7w za%6J$uIKsV; z2VVdLaW|ZoEQv#D)SP&FTDc@}#{7R>x;96<1UxP%Oplg7wVk5`F0q1wa?VLhPlZqW zGE^}$l`TO92NGzDKjJ{nJAAa5=zIz-Rp7lKWLvN||Z|0)G))6&5KxU835K1@;%bRxK zW;nG_*aYZenE!+Ka%6a~4QR7dp%s@C0S3&R#Sv+ij3vjRk7cxkLKRS+W(DPFj9CD1 z3lIf@R=f1+29dsJ*{B)eD-B{iye8v*6I^%cV7*4CKhyfF`e8c5SaopTdP}H(%u{ zRaj25N)!tz4E_Gi=d}HF=O|92^>!EVLL#*Cu|V_vJfSe5yu4g%LEfwNq&v01Q&I8z zXw(=_%!K!9=LwA@HZa;nO|*L7xmNdbWyC>F*X?l!V`G&QS+r}t?;63bZb8k#QCU?S zJ8=wpEJ`bY)N2-6Yd!bY<5DL%46vke@&m_f`;8qWh??VN35bZ&flg@Mim6+AQimi! z=YJ;qK-P#@lNNsYhd|WH{yutTCNbo4H!#%F^`d}Z`UdM;WQkCMb_H9|sfWjxCha*7 ze)#6)&cWdntBbkUJC9lZw`5vcSu1C%55d(B(k434SyB4j~Sf6CFztf#|vLB3y zfVKW^b$M`PwV*KGmBi(+xGnAxVD^c`|)q-TZNEZt?(cosx%Vl8qydgY3zN zC%pT6R%Y0g!e8SKR|kW3hjsIAXJfbeU7piOzcm?hOIFgW++g3?oLzKrQe-yfj~w^@ zajag0udd|WZD@}e8min616oS!S*MkE-sa{zfWsM^LIT*M#V$vS7Z=m|z{eLI=&{-v z3{tX$gR|qoA)#a-Ntrq_lnL32AfGc=+}hQC7gPMFR>~ge_6CN8CTC_;l$9M%KBLyS z?M^VpST%Gc&^s-zQ%)-dqME$a%{{GV9;%q%e{J!JkM>Yh#Jz(`Qv$D3jolpmF(uM*Pl~LyU zkr(_jLpT%ES3jhRmFDNb zX|MDfRX)w2-bVZ#y9cgM6r8a=P2w-aN7J90wsn{i-ADQMehc;Bh7;>_eQdf(I%<** z>mltyH{j3G0)hN9Uj@6ipYcy_f4qwqMWie)?jy@=7)w5FDpc!*KG?hNQog@REv-M~ z{ef}*8#Jx<#9dBr01xydNrk%D0(0Nem|Bd zCP7!h!Sh0>=+i~*=8wLt385;{jx|G*i0sZkyijxI@`HmzDw?pXUmqaE_*~Io9Lj$) z1^oj87~}h@tE<8OW&g&ZK|nwtEoTMD4+{zkfKoXqFff|7RE5cigM_H`N2_<#x|Y7a zf<<9j5atdTHS*nLZk5`NeO5Cc1h%<)E{wh$Bu67VxscF@v4DnKfPqcNCUX|jCu44| zsHiB%2n-Gj1HmUrSU6TY$LZ6jEJbaVBp!c%^RaY{Ss5=cFPOHKwS~p%7+A8^;?dF1 zCa7jbl!h-#)m2o+Hi>k8o0j|_8To?Vn*O`s_k6SOcHP5=MCXFToJqn_PM6iyuXP$L z%s<_iwg+BbgOYb-;_1_MdYYQtHfi>}|Gj4vG2-Af_jJ4fzlx@2GC%ea6gTWUDn1Zn zN{_D&toC`DikeFOo(0XT?~oCyKrT6gp$C%}vgLV_Tk+=PxZk9`@*Yg8Uf;OXRVz1^ zRwf|Oa1@qxKHrc1(a`oHO%%Fqr*2=snCff)i4}iwV-IwM}FRfd3 zUhfVWw?6xIz>S4^5}hODNKWBChg%k+5CzGH7JY{B>?~Uw&nB0A;eUI9b{`Mk9&^p` zo_mwPxvnssJfOo+;g67zmL@<2XV=x);(>HPM_XGm7~qOBfWR>`6O@0%znsU=$-L4U zm9n#o!IX2baJ_0nD45Hq@*HrQ*LYFP)lNRI2LKzkjqV-SZQ@sw;c)gvN7i-63ElFsa|vS?>H}|DB+LRXg?v5@*XS zp~Jt^KK@=)Px&`8@B6Fz`=X)L$5B1IuN5gpX}ZUy%LF~YV8xC0Q~C_nwJHUlb!%F* zr}0b23rWc4s`F36<}gi?xy-0!mXYj3qYVz@Ed7az*XM=(j4u~G3wYq~=5M8GL#sC1 zrxT9es5)*~rSIvd7Ir`yJ4e<0N;kINO5&3PCg%eK zy86dODn;z~r5X=*c6$5!wJVJniOvir3KRj4`9*J{t}d;i%X~3ud z161d?Z&F^&SXkk-to>nn)jz=q26wRcgoTbv3<7tKHbBY~Z8ZuDXMFkli2!EVFSTzt z_ly0Mh}Z}pprL&X!o$Vwi5!-aBhS;<2Q#J|)?X^M-M`09#_->&ZhLM*Ejp*Vw0IFw zjOo8}XXA--{8`FPqz+%*p6V6tt9dOw<=Q=e@7G|fHqN4?BOM}w_lQqCA0FR>dXE~E z=uA0%&v84WN>*A_QZXOrOMXm|G2&EFZ8R6{)49FdVJgjyO&;5R>?3dUJv-J?VPgwY zOJ}5_WGks|UCZ;%=J)USFtXS7w9fFcI!&yt^#j0gKC8%kFxgCsLB%44u(-5zq1heJygWHMIp;Vb4xduU6MP|nDF%Eb zFa#X(Vd1U!ZBnCHDP?OB(?PW_n4>Yc{aM8JPi1odaNlf;+2|^nZF8_zd9me8^$xoA z-mCG6iFybUQ3y<$N$e|QxiU95TNk9~y|F#gF98s_U6RtvY6b?fSyd*ecqkDZc71v7 z1peXcc%}3jy{^Zvc5x>CrKzdf`{zgYl|oF3FWfG1}5eQE+_Y(XX!cp*ZN164CLEcY7Pbr*Ag4&3D+x)7dPA<9A5T)(F#jTnewa%>s)><+?qg0b|&+o zj&jFl@6m_wC*-M0=XZ#lVw30xo``HpkOtyWK+`!LHp6X=9RAE?>MHCk9%igkVuOgd zcd)N^ebdd7B)j49wn-k^92kZPb$=GWvdMx;#{0_s#;RlJqe9M9P+&K$*)(7dSMGfFy|_1^lfsakm|oddluzy!M8&RkBA zua*lX@ShGD>tyY=W5G!so)iYjhoiD64(JYj7=oygnc5d3reorWo>6FOYXjylmV<~0 zN^gopGH{v<4i3U@P6nnou;qgnQ+MYRye2JbVQ^g*S`U}7NISn-b6*2Vvo<^HKRmk*jxXVI^at9p(O`5O#s;Q^3RLX&I!+H6nA zGrjcJ>WX$OJ%3(T>`cARdL8+c_%!P0ebiY*y9pImqUy_f>3iYZ2RqTd8(~kYtGa87 z2vEH*@67!0;&u!hLmrp~K+6^Jcgi+-#C`gd%*+#4>`=7~ud|8KF-BZELJ$WD?!{ql zekFfsheJwyLcWrIwl+yB<0Qxehv%~T&%Mz!LCnm|9qsKvgsZ0vyo*So?AfPT{~-;C zsimky&X@*{8LdoO93PnZ60oGiX!w|9fg!NnQ78u><=|s%aDeb|ntt^j#gEB=hiI~P zpa($v#+bhEa%P`JZBTniEs|83fb4Q0>V6{X^oqZRMoAPkT7adcC2(|tDG&BTX<3(- zQ!z1>pq8ao@b94!b0h`de0qcV9!aX_OFjPvz*SJb8A^5fL?p*5HVEf~Qrm~r3!Ba7 znHK>h%g$yGjPHv+O8gu!@zhASuN{1lI~`T*|Aju3W05Gd{iycKf{~A9s3@!KPqVo7 ziYq|(APZ+}&1$MCnL|3sr1M7Te$cW%WszHFPIXMrk{t=P7Lk@J#~ZDW8h^)gfXheS zFcGi1C4r8GP1kr-YPwPK+ZruD;Jy&gVqW@O>S3i+(6NerK?{TH)@t;SN8zIRxJ08$ zrv%0Pv(eh!L*povAyCF3B{FR{&{l{XwjoC&_4yv&>*UC%zRY^zgmWNgJ9^Q@gv!+(;IGsul@~K;}>&VfOQ3x5-uU z>5mN7kLNT0TQVqzL1JlH2kpfa-;SNoede-pei_L5*)SHGpd5RG8EBY9E8A>@28r$r z-Al{ng#SHQ6dgY&9D4cCc3)FQ0O9&=RWdE@Vx&MKih_dq8uOvq6GRrNgzlV*BS$7`TWsN*lsPrE4ivWc$E7%j|HH+y{wfQ4 zCh!XdMSzS3$1If8sp}VKIFSsvm)N|st_=_Q*J9+-CNJ>+G+U-V8-0j=r3b`L;KNlA zhC?_sm(1Nee~-rDk&^!J96pby7>U8^lIW6Kbnw&t5h}`Iu=ykG@Lac%F71dm98x!G zZb`={(4}EFd_7)|^3(@DwKLzcoFix$8R;B<;r=f;6xP2}bI~F;tLxdL$VENI#n-C& zGq7ULs=kH35T*ZI$j0r{yEp|Yl>0tp;P@yTN=ypy?vpR7ij8c*D)y(Loau`a~GMzR=g_@Imu*}rF7UsF-Ba_6cK z{oH$MK5nY6nt(hyNZi}CD4c2+@82BKCB}d5xxfA07JBoexH$CRi>)V}S{)uyps6Ei|1+&?qZ775gPb}H z+IB3QPYB%@0Yu<=Ho!;*ng6}uuk)cHV@5aXE@C@G7C=+X1_Iaf?^dTgJ707PggoAUo^&*g zKi6sAxDvB@ijo46PQ+@IrANYwhrvKu5?=2gLREzoD-EXJ$u%C@VCagwySeAP81Kn4 zUG3B1%>LOH!B?-o;_o_cImka3eojWDP;4@kR%bdK!I`f>h@ZC9V0boB$obFb>cbgD z{Wxek$TxxT!6Hgqiz2&A)-zWt%lZ9@Wvyr9UH8iJU)GQ0bgi{#4~6F;9FcRlF-fjR zvkv{Gu3m^8I5-!KO)uH?PncKT-rXl9+ud+zXtne3AiFy_Jls7vpnACgieDRyuX(%# zyb@TO62@K~cK`Pv>=<%fDO_S`YS-JsNqwk%eNhI5pQ5jclU85jr8E24CTXt_Uugd3 z3!Y_)K6y`!a0|O;Wh@gsyskYoX>n4!#S#P+GZ}}o0nM}eF2FV!P7y?2Oe1tv+{|as z|I{tI@KVwMrCz3BYL)TX|I7<7NCdL&>ebXYrW+Z~pP?+1|3+iM7*lF_L5MzK>K*>} zpy?}YfAObDENehbrID@l^!Rr*NY&-p4(Fy_=!aaTQnkdycqaTl63(qtu6LjT(vS=s zq#Vind8tSB1{>CYW7e~-`t$$Q0>F=L8vx#Tz_=r;5&8raMKEHYK2KxqIqj<{xIPhh z=w6NXQsRqAXMYiPs@sTOEcLUy1V7|&k2ag0FAJ*ka0$e*xgn$1 zY3HbB6(0+yQZ*TiYh%u4EDhH3*JakM zd^P}}Xl>2C_Esb4nzRZg{Nq&;?Tw02z~t&u6g!UDl#8^%3Gbr&-CYo6W1{_I0J*Y0 zuohfc_-fH>X$QwEy1%^cULEI%Z1<$RMZa4KCdbmO zqKVcJ*fyQFVH8=*pZQb(sC*h3{vSU|nLT?bh;uC@^Vl=9g&a(b;4k_xh3+Vm@y^i^ zk0xz#k>Y>g)q0|Cy&hb5syPFbtdJ}BclS}|A0^ks%PVW?Mg+Rr27QBBAzc})o_rVL ze{zyiJbq8)tnLu2@_(PEMkj)OB*If9h7Xe~V*};b8$V3!^|>DpKFY%G`H$Dqe2r9z zaqE#%(Yi*~&5qpfXKA{`d(yWa_z)68{-wk0DzCTLtmuaWwNF0c+-I@wI9@?(3$LIP zvFv=f`svkkBx$(d=qEZKbqzxdQiDO`)AAw5fUKc2?7IQsL|Z;4Mf)EtYp!7ImA}!HM|yQc*NS-0-nicy7qn z)yK$;O}~^(iO8b2r9Z{J-?&7SjBiSr8~N`0_QAo<;qIY95{2W3Op5&K%$z%Ek5 zCLKCvl}nWoAQxL(WI3Q(n_{Y`QY+KU)AVXhFZj0+FjawOetLR(AV;-Kned0)v7Vm9 z2%_EOaC2ejpV-NVw#P%=PtFwQ9!5}E9z#Vii<0J|Z=Q_kz)6|uoG%X^p@fqGqtf3i z@G0P!)n+~#2*@%T6w<*IaH~qNAdRoC9tiQ29X%#Q#U$hAFfb1<&BH=I>wlr?S1y;} zoS>E)ZN`Zjb#KVGs;Mb8hjVP07@fur_g%P}+!>%U9v)iQ+M4?Rus6h-eb_pj1}~3) zW*-i-q6>u>_iXRfhK`JiQGSSm$-M*!?$EDR57AP9&|!^8U7qa!C{f4A zPMGn1P*s!?F?=4#jyfy3*S9nNXY|+f#vlBvi7eeLA+nl5+o^Zxg~OLMMjPU}p%bPw zQm%Q4Z*uO9!w0~zq&xU!HM-pkIe z&K@@t`??j%{#T>z%UZ%1FR^#+z&iVuKi742omr&c2o%5h<>sXb92!92XNq@dNJCW{ z$#}rsXoe|BelF)yz}+q17uep+XKJ8$e3ni)PtvQK{_tF+RBc>uR?OCA|8jl{t8m!Y zSJb+6@No6|6-&fqCwWPIDECng(Y@Zn?CmhX3-P)+4T!)VWxM_F?Gkfb!(b25gRse7 z=T%g+ZaWCAVRlMqU=zub|3R71Lun2z8;V%Wpunxs(jxBVHfz0C9XXcYRNVjaRKf=e z&CI0S`2xO}g~qm~&-MlFYwetdknzUgZ6l!%0h#({mNJ(4=25oc0V8$T2hH6--FtYJ z@A;8}FMSWOzqiNii)>ZJe+*3ZKc@?asozO9UAuIidH$BnH6BR@W6J+WoqPm_KD0EZ z2yFyo6gpX^XC`*I5tmIk?VQNbSS-FM7)5atNMq)b);?*Aj|EaRen-mecLprjy; zfC|!`QcFrB-6|7qs_#enmS#H+LV8|dVj}!UEEdnuFmLS0oB#alrFFZ0@FKeMhy@Ws za0PrCEQN&)bG+itD?y9Yc!V|XeO41+&7)(_179K%mUo>Jt1N1Gj;!wi} znh(l06*2@c?Nkx%ADD4TiS99;7pDla&f!0EJ5L)TKows}l})$!v0l6|I=i{QPO48t zi2H+!AQW)XZ%1Zof~*9(eOF|uV_Bn)2%-4LYKxvvzkU@0zWe{!#s7ZM5{-C@5x}rW z$gCp=KIq|+Vj#GtsLg&%F8HKYJFN>9Fl$AO@ce6t4@<7jLH8Jg!CzTpZ@Rsbj1WXX6%y(#lrME`Q0X} z`Gt-eu)W_r?bU>c*i8rOmJ3nx3CPk%J2(k>*M_ve$7W8;A{4QqFuTz!JHpfo1qnr9&b);npk!S_6MRssdj{5r)0? z+U;J#Xv6nv!bLv`66r{|5;DA?>hv0nW%UmjM-v~eTPTl`BzbRp-M-ox;`UZ~5^KYA zz=}UtHa+&_Q{*(A$@P)0xl6%jRF-=>+nq&FXCO64XC-r}NHNTy>oENM5o*OvY=Z%U z;NM?`v1ThCg?nkf4=bU6O!~6_{fX(EO}To!<$DJ>T?#V0im^d;gU0;V_-Rhs5Ki9&l;R@P_7dB#PNq8@LepOQ*Wjm-fp|);fOnAqaK6~vn4f88mHG&hUQV6L)D5!$n~+9{T}*uJIyvU zvmSN|=JdM}*dX=qy!hI3RcOV<#14**E>GmxS=o;kYO1QML#9HB*{FGW?}I0cZk+5+ zbHo8m4M^ofa`-(QDbpD1OOuxW6?HJQ9SUm>PVZEGL_tS@pA4DY0^!Xz8RuF1ML8NCq}l}heou1v}n9hkbhI@59KLUBRhz*Y^C`euC?T4_Y_l9nV=Dq!OAuyN3@x_Vr{Vo~YybR3{EZae z#IFotuwdA{^**n@dcp*Icj#SiE_jZZsUWNUR&AdS451rTrrDzKP(&;o++$wnjD}oa z=I&5@ZnK{OSy6g>{2+>@R;%gm{vKy2nPlZST}Kwo1CEyJoH``wH&xpxlG3pi2eZx1 zaQ^5HPFIXWzkbM`DobLYeEKpz);KqDLQ`r6ajiWKy}+0rJPQrSXIz%qs5S*KUW-5` zQ&WOaqxC!zSJ!INk;z2|fGk?c$jJFA+yVnM4*|Oh`C#*5du#KEuROh9>f^^WHhm+2 zhyavhrQV@lFtXR*Pt60NAk|#1p`m%3cE9Sf>v0#~>z-i-{(^J-0AQ{EUhy7h>k=M< zP{PrXWOU-KZDfLCmdvXAIgBW!dW?X(=PUj#9F3~o7Tc6hUPY~X&Z*^1DIYbp*+RVy zNK6JIph`t@GO`WOo&S?j4EnF19smo0LOSUjwD|$sip59@Y@^uORmpj}yWhc~^SmG? zez;wJOoNh7K$M=NpyXIo{1>>efbx7Hj%e$Kw!M6cNM?jIJSH`+2S+auX2lcW#eIo? z@vxcwU4_$n( z$dN;4-4@(&C+M6!3Vp$ zmKGL!dj}g7{K#24JZ!9#16}j2^cBVB>cz7;0Z}~L)CP#52sFQ9`V)ZCq3!YBN2>n_(b4Ty&TQDg{8Bh&WX#)pP+!dXI}ql?56O zfnuGu2N0#VSZ|Xp_W)o`DmprC9=DErlf#~uESZ-e3O5ae_WsFI_VY0M`*vBA#M4wB?mxA*;&}( zHiKqH*J)7S?NOuo&+^snq3zKuDf0fgy6~sVi*9$s`r7~X0r8qDDdecoSv4xbUvM+`o)aotJhtc+QQ4bxoIdaE^cFEL&hKd^Klk8 zeR|rQf}*&fWDqYM1D8-#(9yxc0j%nj92~SfQYVMp@}W`@(1p>_rKPF9da9$m+PO&* z<=;r?dLaJWe5%+55D)*PdUIv$1l+EZJc_LyFErQzFG>iKv7zCp-0bA!hux;5#{G@n z=oFayaId@dE?k{zA&*+X6B_`07Ng-b5M@O%*81sRSN69%tyqsEbw7KNY0B*i+?Q8C zDUz7T6WS}v5H#mOKB{_;hgHAn7Ymih5w<&JCAmCUZUf}wi*(ZNaJ!q;%uf=zmF3?P zG{Ad7O~Vi#7`6t2i5k>sG|cfZ&0X1&YA+p23F%5o6oWBGjCapU+9oDOu{L!Leg3c(9=RRXUCXK@i9k}QE`y7ZXXt%8hJr=PG_}c8QhmXZo zD^i;1YhvT^>-o?NmzPSFZ*J5~3oz4VFHp*chVM<#Yv-LGypok4FzQZ5L$pBAEC85ypG>*Ck>|tBb}#Kaptvjt z?}G&1+;W>2AKU#=)3J8FH5g(_fMOFGq!`kt04bQ98!toiNN*U-Y~{ULumb=we>9@E zgIYRHbJeC3MF3*waW=^DC+`!jyb+EE0(k&%D?qw?TX4v#TwE0H`uD}U{z9l?YTblr z!4u`388m=VwKj`N!9nug{Tj?woYulK#XdC`4u;s9P;{zHO~`Y6GN!8!p(DL9T8oPk zzESyVB)RC><1!60`U>M6q@q1v8!8=xel)%cy(u^&JM|z=F~(d~>4ZO+91@w)R#vw8 zT$T$}np6U{j7VZ67qrPJBjqYTJ3H&BVgCqZ7u(xArU6S!a^)pHRGw2$6{M2n@_r zF(F%z(v^lDThuL1&CKi^AImVas@#Kt=e~=<^90N;T26}&Af_B#SA_z_n8&)ddy9^* z@aT~1mDA1sU3=(WQJMPQSh7{C_@JELWT8^q-6jLoClfGL?d|5LFI5`$g8{1wfH1@P z9uoR>YCq3{(J#HmeA?FGxak-|ud{4yX=mAXe+l4a=?~}mfG6g;9?BsvFHgxwMHQ&H zRawcbe%p!8*L-){ujpI!u;g|;sxt@r)X?eb$!SeH)V~FeceXW0Ni;^tY@mG#jG`J$ zGm#e9JGdn}91{+>jWD_-WL0Aw z&X)&jG=^csyihPBFHy2EFdWB(9dsBAj=7|}pNh+ewv7{)piqs1albA+JY2oR^Qd84 zEN~0WUEWjtckU0PY_ph{7;A>R9!RbVaJPT{)R+9>T;L_}IZ=`(i8ecXHo-7iyk zh$IyymrgR6(nyqe00UpfPr%5utY7s5TkU}G6?Ft`5O<({Q1Ajlo>;iJqRd<>oc7wY1xXh8`Lk23<48MP7)Hkz;8#CnU!^f!R7IoQM$E*>DM+7Heosz721t zRgF1InoIKQzD9jbr3~JAxzSPRNl}>UkiF(XYbE6miyTZD zIlbYSD80kO#?C;|(c|sy4fL}%!JtL=C!<|K;bksB5(32F{e*%{BoqWcJ;V=XK`HSC zSD)CwNVywyp)ocvI5*`Xn5$fs{})u!HQ|osKT&8OBm;EyDhWhSO2= zX%Nj(^C5eKrnZL0?V%qk9i4l=2LJ{>xGpwsO2z|2R=8SX2v+*weBEq;-m?%#y+^_i z#AuU^{9<$Ajm1F_IGR2@X?IBn(|7t`wA7l6o$RI3SZ{(p1dE?EIPZ>49coDDbF*v! z`FjCX!4-f8FQqL-MXhCJy}iFC;&gRhYQ9k*m$_f&wi3eM>qNCedFt4UukpGT)vEqJ zYn>jDIde3GdSep+Wh+-Qe!!JP!+*k<>pQ4Hcd5s$L27O@$ie{cL)6^um?Q(!WtK|N z1%L?4S_R0wvS2*IDxNg5$getKPr% zSE+DHeAT)~j#_9tf0*S??IBg#1`G;5mQS3fjXO?!TwF}tP#U0-d4QHCS# z@^s0F((}Q(W#~BdN`Or#>OdJQAwLYB<)c3XLt6Ia`kOuZf;GHpt^3K2T5lyg1>RqAUcab?#g(XSy~yzT~2x((YKA9RS= zn4`5dBirc2gzy-9Y+!J(+g746UIBn}9A<|@B<7d`7s1pGICCsF)43nX$;p9MoUlKR z&h74`TbyS5k7vQw&Q9Du&q93c3*N~8Ub6O%`qi^%#P+Z-rJ|qc$H^{zj7IoG8k#E{ zFUdS^VAgBjt4?hYdMDSV3b+{Aa`&5=O&j7PkAwv@AJA?tj^`Rr-9E7mOtPNcb=HM3 zL31szyFILXJOOnfAVLtmdH< zPoGw$ITp`@b?(-{&)tKeI?WSmS}Al>Qv--JHyeNMEUvcm7kkIC&1Khpx_|o^&sW#I zXh%fVB;t*x=r?~gk(n#wDu8gUdMxEq`9uR-(Jk)e2hD^s5?OO4fnzVa>3d00AmiKwvf z{nd+DuMNJPVQ~!NOv-7RKY>vjZvdE-nq91`HcC z(-IO?m6fL^C%fJwm~pVO#zZ&6X9DzRW>G`HF!01|;TSTjX==U-4Y`oL_M4DY=PaZ|26|zR~ z$QQ-Ee@*PP+dV@)Ya7u%htt72AvcyG~aXt?Fv{VL@i#Q zh|NSOOc-y+vFgmPE=S(B_W|3*^+*JxuY9JZ%Jk&q#FVS67_4a83+JE-G?VssGnw;A zO6m9(KQl|m^av%u6eZbAN)@~WcK!}nGc0>aA}CJ)C%F}LBCINdNPWYXNh zgPrcWR{%JgeSLkvq46i1TL146|5jcQ62E+pDCG3T@PvQw6&BK=3`m6H0;FtdFPeeM z%7B1pB(5_&v$^-(D)T+Wn1?TbCggmr>97{%)A~?QdxJU zq!HaD&Ch@f_VCcceQ(YQnc4mNd)QD|F#PsmIoIbIvAyk0N!)7=Vmz#k{L`Y+(n`&z zb@FLH{ki`2mNmn_oifTOj3JK|{~9tD$B>q2!LYt2p3BJ(@7F93uty;w(ShDB)-B_i z)&M9i$FeO=d|W>^fiwdJ{^nNNe2tyIS~9>f>i-Ji1+vNu5A)4X4qyU09P4`0IWRL* zzi*{#y7NWCb;a%YVK^uigH*JprZz4f=ZD^*1wE8PBC zr{2S|itmAqzpIlAOA3=nf#Am*=;&*INk_cpPkJwP6mn9Ni0rBfiJt+E}`W> zc*Ei5e0!RgpAYoFiP#xUja%j&=#M{H^t6T1bsqD&&rI%+{;Xy$Vms1l-J3CEU5vZ7pWoXYJ+n7>4HXX*Jgm z%JqwVB|Lb$?P3t`^jWoJD?p3wiz$P=g8! zshtiNMn`0a>%o4z6zjEq)ad;9{N!SZY!7Nxa#FH*0vggYGJN$n(ddOgkV6T*oUasL z+Y*uaQ*GGJ=~rjE?dEiP(1u0((kJ4}KJ2j^FP$l;(|vyW$b>oKbUR^;DNol%RJp%z zkMpJ@lPqeF)Cx~7_oZ2=-t)km%1Rz87uC<2%~JH)gxCaimk;UOWEA;P?wUZ#plFJj z%EC-u#U9HfyKp9kRViPHt||-Cc+)HqlGTIVYQwO`u%^(`Kmju&$xcahB>> z)A;T+*tI7$Nd^Uj z7&aXh6`<$e2S`u}2?@u;1#$D~vfD6ZcP2hN0X@C3sS=GT&l*322%0!r!*8U~y-%Jz zA(u&X1s2%i#ip!m{jI_NoI4`!+WnME`e=5b!0NzG=G5N;GIO+pWl{LMyL<7$5%Rk` zmE!u=k`|A9r~}C3)@;5;k{_l5or6SI=Z)W)H98)%V`H|Hr$zYjSt~c>Arnqse0=g* zZYX5UQ&a3(0jhjs=64&mMkXvKf;`B28-4IWm=tw6Idx5YHI)|MkFU>(gEexM>u|BP$F?{)0DLT(v4r^5Mt);qWkqHtuy)1) z`ub=u>+9F$xh^a4q)N}x&^TQ;ye}!}irKRsXDZeibXt2#THFgV)Na}3ZwnKXF6E%L zwI&Q=4_{#IsVN3qs=!`22u045;820F%=kARf9$S+<-JxDmBm=W28OWZhivXmTeYJG zJJIl0t2#D&)u!7+X`GHy8o61`w5+W5YdO8#PM_C*I4i5Dn6s*z+RIE?MtO^iWSoOg ziqZy0`2NbNY`X=IVGpRiw)WA3hg*aF$4e^u2@zRY>$wD`nAfYxN$U_OHAp~HQdY*B zeU+THG&7S>qd^mxbM%hp`zIX-pD5R~dM2+*y z!qLU^{caW)dC4~MCgawmHi?b7OL1vQsQTib6m$I05Hie!oSF5ow^CzMJ>V>)YqjN9 z)S~f?eG=;YL06Jnr+r?R%_rQ%_O!moTtYIauV3;<=i6+(EbyjcV{4IP%r5hJ#~cCh z!}lG$QZn(n81W~pyFG8d2-w&Jp63OTnR0dYtE!b9K4x@|>Mh0mT{6*e}V{`r$rN_DlYU@a4lukQ{UvAfWIv9vZZ40<6zozk%I zx%~Fa<;QdgJ_ZIh21X(~d202sov{ozU!0enf{?Yfi31x*-u>Sv=Zj_eE_<>KtTrjS z(6%GqGq^)%F=VjuG~z)G80<=5d(grHHQcpWzF>#>8lTG)St1wzYSmChJ2oXn(|T1< zNy$)6ZFj9pg|U{Bw%NcD2($uHJGw<@=Zi+&-f7cPt`yhQ*1BJJ+^%XR}&1h9#v_ei^5&;CQZ` zHIb=Y1azXq-#$j>2!wx>bAJl4C|m zW=ly)mQ>inLYniU4O`c?X(0w^R+c`%7tGC!@VnVL8|1i*6XfOQQc*Ih@}20)T3c&q zB$w>IyhV$cnfbYvCE4|E?!_&0YH*EQ#nhCMd^#Ag%o9AjZ5NMq?(VUsEXMODrxeHi z9TR#L@_@M%)sX8KbNTWqIDNI@yR@xKvC{sjhxL&58Knp;27I` zth;a>T0~X4*)qipa#em1ngl@kUqE`642X=NJvnt z#M^L9)Pe4okUyGraL%x`r3-C;)Mwk%jptC=t5PkS#nEih`b_KRl>(AH2tnVr*)4RH zr-o&66)9uX(d`mVCo?hmCOKP&*MiOPdX0$;Xno;U1D}fK;=i;_Wh^+o05Ch_8U}ZD zy24>%2M357yXYGgfPdhirxz$4Nn^dgyB7_4m6}wDN;lkR5Mn>VM6W^#R%Gx`5rDNH z_;I-`KHJ&p8;gosSy>qxa+Zw!s?kmSzLU^!h6DU}#B_@f4|C;skk;0mKn-SXIk~i$ z6hR~gCG_X0$&8 zxQisd*GkP7HCLdjs`?Y?s^Ol%6-dIueql~b=_W+p9kwPLx1kv9buvupY$~e%5LdMk^U0C>xCpF7uJe-!u?4T~FhiN(mKpIjc z9P}J2`Ti!a7E#LmTP4PtcIW#zOXwXm2uw@vbtfFMeEHpaN}j z-RgfiGU<)Bs1x#&t`aas!HSQMPY5FZ<5V#<+Fh{vD)w1(Gn zBcS2ok{60tqU_XXP>q^%c|#df{B&CfxA%)9t9b_1Jksswj~=zya!G9C5x%xtf_jWR z7#mvye3yPVjq(A51T2n&So^t)Rr!+Kli3X!!&Ckfp_!ydza#InMMK3&;v0*Q|o^#b|=ZzsE)xhn{QOEEgr@b@_HgCXyoE&Un z|KMJ#j*AN-RqV*5!e4PFwSHZT>Ic>;BRVkA-CSRX;By1F#2Buks&hfuw2W>wKrt}! z^6FovNX^|vtqG2ke2VB`F|HgJ3C}&MV6JUxx&Hxw_JDSQ>M&YDSN$a(nL$}GMp;P- zgs%mT0+gPAX85@6^vi5L*Z-TeIyY+Ul z!aszABg^`I2xtwLXs`pogwyC+7id?2Ek5%$^-jKl4@V7Eun({*+AgucVGO`lM_Sy$ zNDM4oGJC*yR9b)JH#W8wx@1E?F9m^yBXL)f^6fB9>5n&}oNccOX*)IAYS_Ny-D@!`L|K*oy8G&ZItz@) zKfUp~N7=2Y0p|o*88MzHnOYX&D!yZV%EiTXZj&CZ z;1`MDu_~DM1!2)xl7(`E?J;xQw=AN9T8Ga;v}yOF7=wztyGPASR}|N}w+c6fTwIgx zj=&DTJXC6l>V&p=FYotT?q&crfcJzOa9YTq{|3=nqTCGLup;kdNlJ=+lS)K zOGLw#%XAKsKlmy6C@>vr z_h|YhLn6=VZ=1xmU7@^+-wdS9T>}5>aS@L5epII!PEurQYR45%gVN2|kBdKh!_SSU zqk~Na2X%S;wsuSc(EDaFRMDoSUoZU|B7lOZrka)8l9)=Knv2`Tg+5xd)XwgRxv*50 zQo8Odg+RwA!3(A;%2>!mixOx_{pAH9iLmNvf8;zPN|9?qW8^xYFixI*i^P@Fx}84n z*4QMi<%f6+K?k-B`$+crr6r@w7rDGuLM7~j2gnpZvlqkAxV@mGvm|QENW4i)Y4r2P zUWfC1Ei%nV{zQ#A!Co?=9DQHDbYMg>6%>%}>VYW3|9!4UM>8!g&FU2+=GU@F*a%(= zQrQ$Emd8xJi?jC&*=MmPP^VzQNSL$`ADSu}B#^dJP#|3wb1obf25s!wy*s-1SkIrD zh|IXL>Zg6Oqt9>0` z^Gf=A_)zKk<5V9v?bMmqBEr69`}+m_m_LL1<%7n3K0jw3Xkx6khw(Nv&|`xvmHY5% zceaZNc+}RtK|T~Kgj8L2`Psau#gggm2momne?B|}JQHG}w-8rS6jnR}6W$E*UH#P7 zZnt?1@{e@B(9dIGSGN!+2M1~o_eSm}yxo&A*E!)@BhgfB1t_YK~e!C#Wg0=pSV zaCJ==zqL&5;w??UI1@4-k>uY9xKYTaA6oPXaxaxZULGEnP{;E98yf%oXYZ@GgkpkU zYtd!!Is5~r^^!^Ys%zN$H<9=ry;}{3oeCV;e9h$owig1e=!Cj6iTK-`nDBAXkIPRf?_#y+!) z7yf@o4bvWs&m7La>MeDy?wAaB+DL5jb+u^;&^@H`hjU zbLu;|uTP$QEioIx>F)Xg`MLM_On~J(bcL39gwh;g`iMjC7ZUe-(*h#L2n-gD941;L zf;2UK!z|>C^c@WEo4U2%wGA=6rVH^VMYV8o6Q!;9x7HWg7amiMTRHYmj zqFl}%RKd>jH1-R~I{n|rnpJ+U-siKxYXq40*!YiGa|NrcQp?>~QBjAo(Tl6^!acK7 z@*%;jK(uNo;!o=?I-YE=_McM*=H&qQfojih-D?YE;$~PFciCsuC847oso!XQ7e~xT zo>WV!2#c+hbj(@F@PNyNh%4~-SO52?W;lp%L}S6=8h{Ghp^fq^W~J^Tme_N|Y~fKWTehADf(1g2z3rwYtsB$_j~$0q!tur+YdXz8hU&o|%0DP~E@* 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

XSkcq6^#`=nH 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 SnDHOK@zb3=s0|K5y#D~VP;X}d diff --git a/docs/images/prowler-app/slack/channel-picker.png b/docs/images/prowler-app/slack/channel-picker.png index 5b02a986aeba3d940cc5e058ba4a80b81194f754..bb1bf33bc04a5916646f7a8187becf8f8bb7b95b 100644 GIT binary patch literal 122935 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

&W;Y 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�&;53aXzhi<5)<@8zil0RP!kErp7(xTyN$*3k=CFG!=2*$kY$sh$`7e$!F3y zskIVj<5jM;wLR`c!++g$hB7r)RRNLydqnWZ1G%9$xjFPu22oC{cXuw&gT9?bMuIP` z-^RmAD?I`!qQeZk&euAqP*zKY6U%EMXf-@x=Z7Dyp~OBbT6(+*-R=#=R;Hy_t4nHC zu*Ya_&5dDXOdQoSUnxxOH**SH(lTY`)3x7$Clk-S2PnxofE; zL`5%lE~#R59n}t3dV2CC#-4)k=EiJsCn*U}I+K*YRigMPbX(pO-o3(??U=Xx(qKb)>6J8Af<^xxc-|(6l5sz?;rt#J71TmsG9trMo*vL`1qf zhVGPZDM7lsyK`t5-s8R3`@PTadFNl5@e}8qz4zK{uSJPsXKR}!;yM{V$zrLoJ9#YK zepNlRp_r!-L=2m8Ig;Jm-}Dn?`zuj70$XJ)P2jg}Ab$`chBoP%;%t?+-tqDkg5seB4V$trGd^;^G3Jk1o^}&pH zz^x{4$ZEb)kxJR+c9oSx&$9q2@nJTPXzI&?gV48#`jhn^NZui**xivY7!|B<>(2H^ z^Hhg31yEf4K!I92nh(C4Hgpj(3s?geE1MBTT(!mLR_(urvp2#&bP?CgGkK61qKaEs zZ(Ge=9xA^btkO1}_#H5!)xcoTYPT{(J5{XVQnJ=@->G+(L|aM+Xy_;dYntzdy;3Hd ze#^+<(BGS@;f*sX)ujOx*0ic{Eee^G12c@XFZXkU3N^#hNaq?)z6IUbI0Szl1Oh|V zP0nIhMC|2tU&QhFC#kPif+z_elXgnOI3J@tVK1?A8%!ew1=0hzYz+F7KJE6|8joe~ zt12+`ke;@2B%@%@=;TMvOOg4FnK#~g^{D3FRRnbtHYWcqBGWbO(8h*Tv#Yv}$K!f~ z=*0Pafe2L&MAH?fO`ypV*4e-DGlteKf9eC?>#ZiXnmi-kIuqkVjxgFrk!u|V= z+&~hwK%pjn==@k3QcnaQH}0y2+>OR25BXGkC-4yljLU3knx!}g0muw&w${+WH~W!7 z4&7@NMpDF?e5e7^iLCJ5X2fh$Kgwiy`1R}Qli(xG zMvogHpZLM3OMlz4doJt#U!4`CP{VVF*RGEHQW#U!(0!ue=E_2KcKZ!h{f&X^2dL#1 z<9#<#9i6i2x$YpptFoN61cqW>pC4QpuyebgcUIq$xXG5Q(1|rzn44owPgXf$;HDO+ zgWlH#U|m>E)o1c&OZl&2Qz-3>6<*D^3h&I8afmrD0WyWRH^efT&Q59Au=i-S|F$2# zX*KVrRM1v=&R`Q~X*2T;gjABwS2{74$)Ib1PS4%l1Nn4!dthJ-8xPrXhk$dx+&UB3)Gj9WZHyCReVw-fb*@l2H>tn2iu+|jD@1{Z9{ zhx6I_D&e25Fv^rnbrefCwwaJ0gdETK91DjKs@K_`_($E&Hrl-tkETjT5Iw`hbld2B zof+>h-QZCVsRZyh3I>MNY+glx_^)ZF=MnV4*td4gaUap356wIx$nK{ynMChOvJkG6 z_ZXchB_U?)xFo$|$tjg5)f}6DPfwqxkvUaWto`}(Jq*Gb>Lyt7wbGZ#@9V%aiR|`~ ziyJia`BaKZ+;>3&0(CLH%^PZs9OG1y_8DzXS#wVH)0co3TDYYa0W~!?{%B=XJW(CK zKkotjJCEc}<4MJp)~O~H+(K&Hz>t6>A;(EZ&)Hf~K5*&smqP5f@FP1`?hiCrHjsfG z&FXOUo;2_CtU-6!a0iFY=sW)s508di8~@lie5|q~0-e;?WIxH4+(zCjO_r_KyC0e_ zOqE-$g!s=(Rq_4;wTD{X;dU>!2tXbU!1Xv?(2$l2&z6_NB8}Tyti!Rz( z*kHedSq&X2K{tKt2&tH&N%JC<2Lz?q zozEYwn%uc_r}gU-mlOX4#!8#kuVPUYNnB2zo!U@YXKJf;;JVh}dK$~*b~qBApX-=@-`?t(O3LcybSM zZ8x;?3y4Fat@SU5?1IWITRKUt!mu}$9~l|Go$Xrg%0{6%>u5ymF|h|#iNTvWZ5`Km z)h!(`CZ;`Uzb4(dy6yxNd2&u%;3gX$+O$%(=G-$Y?R7?+JMDH^5ch^(2);dQ zwAV9fV`GC$tBucN;%+VSNPhmx%NzMNNAaq!m&2yCvMVWo zyhou}m~qp^8%HKT7QOqe68_X3GIrY-rYATx;89~FI5;S4HcoYnI91g2`GEvgpC;a3 zot~KTI9O5|cFI;L7oK;m-DeojbiOuw1BVr0vL}ID;GqNz#1H`g4Rv(SMz1al&##y&h?e|vr#9?T` zpSFx zh|5*XzpD}vx5)A%g7KmnlQQD&_;%G?{l(80@J?Xr34_7h5s4uo(g{k`fM;QDVbKJ+ zPObOt$mcN~|6W=OsLzU~zG+&ntQ;J|LPC%^_iwaL_V$laQNwAACCm#8SEfgjDh!rv zzhe;(^CN~1ntTVn=K>@)YH=Gyo)maQ7zb|CU z_L+5ci|G`xyNa(#&rqT$rpgySxJJow$nHKb6*Rle!aw9zJ{HdAa_?+G)~WT@;OoPl z$>59oWC^0bh;^8S*NCt6ewj>dG=-`^upI~CQf0em5bN)n&NAQtg02%H@BS@mG_}G zJ@JiS#*%=oIxJ%@;nJ$}VQ{E(TpHjL6Td62&^zlRtn&<9Zy^mhNAH?)J>9ghvJ$=% z*VNS1LRSJT4~JU2y2L!))8vgEAaxs)!)oR6UTqiiF~uk5@)i-LRDn{+AZI8qFQ-zh zy)Mhf03$70c?vaX>r!$x9r?HxQ;uof*$BjZYip}orMdL}(b@hlngi#0+x^@1_gyIv zhTfRs1!4z$%gF+hnyv2!l*w#%foVhR4g?pMuEJk@p?=RcxWvcIcc-1Sn=IK3;$b`< zDfxBfR?aFfJQ812nU^nW^9%1!*Y%EfT#e@A0`{}qmJhzYZwr#-+Z zN7!>0tvvzRmZ_Ehf|*IYR2W_FWavgU$u$Vf$cky_d<{|?kZ-1OuWyoNbU*70;=Vzs zHQFaflz}?u(UVuC=U%*b+*JS}lF4spysBOvwGOB=N{o*Nznt6NLzJHqqmxsHgaqU( z)-{%v9=4}UZ<-OrLoG=vUNcpbVKixv8UIcZ!0h28G?r`OO3_(pn+JC zf~ly5%+cuBvE-zq2J%C{-Lr6=+sr2%V#Nf--X*5eAS!A{Cz5{(OR03SNm?f$JK)o`IuT z@v>#6#v$nLJm`@XUpu9KZIu%FHa?U7wY1iC)jgVO(y&KO0&)=3PkdViX5fQ^i6(`; zC%-GYP00}6X};r**pWTKhe{+ghLTv}lVnPnIN!T>b1|DcFv+$Z7#FZf&-!3EA%gf< zc8FGdhgg!ElcnSSB($TlZMznfph3ZYLP&p43YqBdC9=VDRLi0(hheWYq?#`9}yo1;i1Lham3wvmC2X85r6a!3?Ijc`ov4v ze5igWB_-7|jubIYC6`g{>+6U+44N~Cs}b*p=fDIoXm;nO@*N!U^L9VKWq-3h2l?vL z%5O z(bhSkk~zRg_OR9@_pJ>6Edad8b5g(&b{$ami6o4)NJDl~r3p zh?w5xkyxpx)(H2KqplBI7d{I9w19+4^x`BZlAB>tHAfs4_pMY;K-F%Uj9N2)bgtCH zTNmwb-qMG}>T1?Eddt-lDi7nHp3UXnN^AC?f4lx_(&P`{4|*7PWB#3#wY(<Lnu=|>A06|K454kp@E<5j`1z zVDVp{Aysn;34Q(QByUXbp09IEuKT(p^V=IP8lC=+dicco8SAU`fO(Ojv9V!R&DSq- zrg;XIM3_m{1r)1;51-$oG}{J4rDR_P6l5Qg7~}?WGR$=9Cn=(U1)Mh2nL|8I32IuZ zo?aksp({{y2j)j_TsUMDBpzd&V`!?YYh*@%OR&AWe4HMs+qsgPC$Jfcbq|cs>XIq} zS}#yHml6??(WWgmWJey5msdrr_VK2(d&G-_P5$pO~B zpDed8mr9-563H$%-1sw?ii&DOTh`0V>oZf-Ty>hDzngP4g9R3~+EVvB>8vt9fOvtA zFO|p`XW~a2$n1{muuUrPL_D7mN&acK&L9%}AwSf~^U3JKZ?k#KpzM6e3u9JfG!?!$$W7 zd1akdR6fec*bjx1`Q5)~oOz$wCg_QmA%pAX^>Um-PN@QM_E)6K4)LEqf7(B2A0KCt zGC?6aE zDe$Zq8Y(24Fd+!ETIE3z-!Yi?^EV0zKWr>4=|zF z*#!V$<7Qg5>^>k>-BjatMke3?J2G^#l8_|+!-z!smePTw=GY)Y5sUkdGAJYf4F$cT zwDO4vw|t14f)%lqUwxK>PWu-u24fQnZE>D!SrIv@;Y_|VSi~-wD6;^CqEGEp56Tva zP;N7Ias;anX};K|os5i3;sD{J%wEfiv_Dt?-b%!2nPRS-H_5`Sg<88@z~}LY=m`K< z{+1~Qx>BGG=75p{0-ziGK+EFxVZOqqEph!^K3dB0%CGqf_4$d37sBt><=u+U&Yw9Soe zA#FNN($Lq}S8=ZPPHHIag0X#5b>;gcu$a180Xqv75yJ;tbOTzXE5rF<1|RhK)lxp{bh(GToJxnEy^6|Lpj9s# zT9eGrQ3aE1mY}zDc6>Hl<#bh53<&b6fx$_xavE0`$HMG}=p7de&4iw<YC#6vlC%`hI$5Z)F4iQ~e&}^K?kN+sdePE{-Io%QFB$1_FlI>f1_M29+OGFSldGss2;b~RAIHq z&D0w=2b#zWX|h87o1Quxwrs9;uL%i!>5pRyBZ?nhr#GMgFBUr9C&_@oyV@E>b1}e; zp+`Qo$esnWwU%aP9s0w*Zl^?`H}2JrW`sqh^1E{`!3?RM|D-eD=n= zrcv*lYuG#8#lH($Yw|^0R(n`g`M6gn1TEti=~AucleRJmz8HIzm6h0Z&u47=+vZ_) zZpGf-m`(b^yFB>mvUWoxWqK2%4qJGwAOCCJmRRw;ki z@#OApWcnmqiSTpK+msF?dPhGB>znq^>RI7*yg5dH1*JG@Ng?uqWlK)M*lNHxg#eNqq zs19EcBw$gl9i9L32FfmnK5#{m(85M4Y@3S=+o&zzD0RJXl3WRHh?2I+Zr%0cE6o|* zxjF4J{a&J%FBQsTyJKi!b6u{f$^qE47YEHrJCk-pdYj>s@POZ&)}Ivfz=jPUqd*raq)abTuXm5`d(OVGW z@1G_zH8>a-+^Zr)lrBFfdFL{`z3e<&N=g;XtO7f@y^@lF#+$D)ZP#E=Ua*30SC@2f zG?N(~7M4toHJx-nz_(J5awox6Y)o$VBkp~D@bD5U%c_mKWHy#}wtwUjAHvB_vDFoI ztf*-Q+$67on-Z`_`a4ets@8;fD3QPRU!T7b54RAB)Y~{HskUCdA71=RAlz87Kv}Ke zHorGef6+F|CxetEn@#+!9AV6|NPq(jn!U5;dcBDlRwl6&|kWXr*8&RWLT#Li;PitQQrV zLM_X@-9X&%SbFp5tDm2rS%n(t7Spj*rEI@Ef=~YVkpjBoMtv{S$>V5KKO(Mco<&y+H;*#5s*;nCg*mSE_vD}n6+any9lGmTU%@T~5%v7%q zcVJk~)tj1|Yc#rJyIg>2?~TQU4aW0gS#It*jJ>%ST8d<`%%X918b^xXWjkL~gOFfJOElFq^e%W}y&PLIn_X5g~3DS>WqM$`jxM|1PX z;9xIZB84QKA)=2iUytwsqU(hPz65lVe)ylH1!?o=z`zKjjl6?nS#8{)X;*~70KTE3 zxIlDic`P#ZC|w(trGi74q1Us}_tf7#57`)o))n>(gF(T#G@>9|$I9mW^?s=Y2vwX| zeq*`QIlQfg@D%Ig?eTtKu0pL=>0|?uECz&E0bya;CkZUtUUMD~6?0TFJ-rQ|JzE5w z>s8#81stzvGW(5*2Ho~N;60GMKcBa~eREX>)RRo+(i-y3dY{u65OLKL5ED!L0hz9z zt23*dyY0gunw(!<0aXRLteIT#;v?)l5K8;IkGTj{G&E+irIR&lPYX3NT^n43Zth(- z{u-M}xdxsAsWbbbH&yuyaR_&@-`&6zU^Z7NQo z$Yu0FX>zA-cf>kV^i*|R=k+?xaP3MN=J1FncZzfwGKy*`7lXB9WvO2FAbCC~95(v= zueAa_+8ZzWq8)P%u;BN{Er_n)z$XsOBy2rNuap>CPIF zAr^o_>Ysbl*A zKT<kSD%~Hq{1i7XlZgrm za3!7_KZ@Zj(TskGvcTn^ya4H-j_$nl!tP!zEb5cEgEY(`2O`UGq2BRGu?jrRerUyu zTE@qWAz@71^x$>M~$zr4ajqU;N^xB7G_go^9w|dy;%K z)p2w@N`hrbVrE*pSEkSb5FMov2R{t5TFF7C|2*~#f;Tjwm@Mlm6pFEgg|%qJg{A}x zS)RV%CjVdon~_GP9j{8F;td(!mWZwA2r5xlk_{Qr{g$Ww^YSv@O+Ge0#A6iiN*SfD z3u}3--7EwZdRVw`EthBLXXF(ocuAF(hW|g=Xe9cG3{qCPFkVV5n@C6Ho=Ew}>B9`( zIIw7cE4h#Gx9o;pBH;Pwsb5~(;d=f1$j^Pq3+_;}d*fv3I5{kS*ByEntGk^vH*Cbt zw1_F44c-!fQ8)Mw-L@ylFz3nsTpp4>_b)3xavE=(*!zXOdpsGpT?Egm#RS9rrPPPX zJaBm4sF^E5FgL`(TN0FFil!el%Ci)zV5Y47wkf>3_wNEhg13v*yh>s)Hh3Oppf-Fp zV+7WtGgQ`s{y$5yiTe$cmtI$@m2M71hp!GT^c!l7gGK`{K^ng%;j}~qX|jWQF#kGu zA;tBtxzlhP>Rt)_Z$aaQcooTeSLEc71w`@;VGbER1J5~|0a(k6UKWcV=QGgJIXL!p zy;8J)$)&E&K}l)$H=c=v)I@i0ucN;=1zSrh`#t_<*|&HR*sy$1yaSm;Jd@F!f4lg2 z#r8mN=QnkNY>7#K{;xp>xtYs*cmiO61mIS2PqO86znk6i_?C|3ZK;)6-M)q>iB}Dd z&B%f(2%%X+s=QZ!6u!rG$znPqr|D6<#`~rq)qqgASaP}#&`fkqBoMEk>HRDq1w0h} zf1Z4(7Jygccz{C&;NU($gwcOB zT&am`MxdVM4NTCeG~OrOFn{*G_gf>?mZG5|NV4u!lSyH~23~0~YklxTD*C7WZRkJ$ z*M})OMn*bOrB{h+-_&tF)TyP#;17()-=dY}0&UH7Cm8Q)m$K*XAw7WO zwy+>-^}_u;(+(T)AP-GGP`~!G-6j9i(Ktqax7C~zQPde0AK=lMl_P4 zYF1mcfLOvqCyQF?49n+DUrS;?%g{{baZ3yh{g6FhZPQ)vg7$WIPimd=T&sItskvVc zaqY9Tq#GvyI++OGQ$GsLEKb5-byY;=nq^82U}1uEGVozY zHV??GcWVQ0Om%-`lz&!bp1JvMMQ_Iloea&>WLGLnzV92qzKxu;M$PDgILg5Ka8ic#H^SShB8(7CYM!osAuxC_uSJqiyE{SC-Qg+7&@ z21R7bfz#skCfvtrx(F@8r!2BK>0bslNEjEvXJ%pm zoSi8@OkdO6!4I3%@+?z%zRCbD5X*_7iQ}@^%6Z9Vr(DoU?Z}(1)^JH|)c;bw(VVFL z`>5H-qIA<2ag&QZizx@iGp+1z@$9zFR>Nx+7UsKH-4MT``IOCI3j$?C)qCl=yKtQQ z4KIgAJeuhZ;X#tp3_6 zRdE}ffPLy!May*}p<>|LpJ$*b)4(`NpuW1=s%5Ky8CmPRXz%Pi5wxvLj@+L>d)o>a z_I#_j6V%$NU7$XAQAJ~2;o(;G02x_U&13zv0-STl)EWR=yW6#qlVhdLgZ$tjI6yzo zZ#UmeqoAN11(US28uiDYpY~F+XY9{6*sXMC8k)cGnH?O_u-A9jNL(WX)BNK;=tBgkxD}MZu9{C(GfG0DwAkz!ZWVy2N6{t_DWw|0o zh@xi}emy&#${aANn%G<+fD)x}=TNYgkK>2tp?YFVvH zYU#ZYZ?V+&Z6_c3B^nm#^%YygzVd}nwwkeWOSe;v@K}hsVA8UfCWs)3e-m{$h0m0qM*X4g{6r1i`_-} z_&5~-pb?bWabgy8ffVzSy`;>;cMrfOE|)9KfNyeh?RiZq2u6v>(X{IA32#ThXKwDW zqN97fSUZ|RGx>-c_4{rAoaPU~(i0CP;*TaO>~FEK9_;*V+uIv6)8Z(p+s>Pqot>3b z`SvO8m58X56A$#oKDV0=t|LScI`5>-4f+mjc7~2ISLf5Mam9PEsHhq-F)_38{RJks zv$16A?2N1fS37(6;c6Q@Q)xgbooa{5MKYgmOf~^R$oKEIr8abOw@D1@_j#51c{n*E z&&aX^a*rO{rwTT&x+QET8F*06@>AtqNK#E{WF-2d0q0|j#hk?a2e=C4 z$1fW_m!)`k_I=N+T-Ir+TizV_4_0A4d!}P9sitN+)MWH0zs2_EzdgEz&RyL;hY~64 z6D3l*YEenS(wMN+EpwS;RAC}8v{C=9GclN`t?l!6#|jCvVAoY29rXWxd zG3@OpaWG#utxs&Ee7G%CSHfjYTfSn!!l8sfI5^m3#H8*?NlRA?ni|)TXh^hob_MF~QEqKQnoOkH>0pVHnF!z1hjKhC($(WGm3%f1k;pOJ^`( z9yg@ZwdYeowG`B`qRIcYTQMjg;1@wc9)1D>?d5x}zGOBK7i)xq5+oDopcg}I_F46w z_qFI;_3{w}GvYR^@UDL>u#sfEj-nTy*8hAcFR=@)3@EJTe!xt1lOFpf>f#`b8+Sq# zKCCY`D))GGC|AXDww}>&M?WIo5X&PkH#Y>IVX%AJTk~G+dufcbuR-y$3}jaAbNJ98 zShVuy=2*2TnghBd*{!G9F>aAAfv_Opd47TMIJv_oL`}Ew!^7nmjA)0(2EnzT99STb!i zWr^dMDe_m`+%&ALpPo;&RCO;~XXq{KPK1`a94qalp#%Q7Vm|)nwsIzC74S{2|0yc! zC+6Q3_|*Q9pkTY}#kS$bhC;4#aoBiOaSOiuS8l_ZNVIk7gEcBNPTV~B>Cw(m1#Zw6 zN0Y%c3op+vn!7DPDf=MlxtuCn4bbEas5|ifF&+=@?B{n)qu>KUwnXmw0O@b}%Ehm* zA{!Ss268#t+w8M6>rQl<4n!nHQ<~qqy$dI@wu_IX6z09RHlKk-o$=-k)50%xT`K6{g$>zRT!GCACF`2x<7iYku^Jz#iDyI4a1< zyrj1;&&p!v@;IJa8|&?E!AHJ-&Q%SyD;hll{Tw#78h{$h7<~M3#!*$Q(yJYooJ>PX z>aaGVgV5xzV{dYLPspP)wU?B@<6*B>V$DQaa%6k7-cPt}6&)96vocUrx{Sz@keAY0 zjJiQ{6nwxw01nuACbN^-{SJ*OJELH!L{7Wehh|+z*EctfXmR#C8wX!MTbXL4BtN%6 z#ZxZ4@O5-@ax$PyPa^?&Gb?nlD>ilmx1Z<;AB>=$7o!Z%anwI~45xK}gg?E=U-$Ed zDXNI*!K5-R3=BsYd@(kglob?o07F<4*~BmBlR4ZZ7HSeXoObqe?O4pGqN1V%OY5?t z!&CEw{$K&jP#!^T3r}Wd>0Dwlo?N`utH9X%jbof@YPC0)7&n(E3?3b?3Vicp`f1cl z!>FgHI7i3EH0wOUJ8tH^^Ddb9<5Bwb*^}b2qG`{~7Ko5LP-A>2O_Z^tq8cZDlMp|O zb556SCGYRNOy_buUp71>H)b^>sx38ebvyj-oz6YP&KBRkFA>+(u+u$hqWOTJUZA(@ z7BN%j)^LD*e0-c09S~E{+tYcybV_H%7CfVYT6}d%V7or1i0rHUr;Lw$hZ6jGDI|P= zjAVRmJT4*5X>Wj6E-we-z&5E$Yi=<+GwZ)!MiS|ANj0WmGq`{7&K9`eQo5c~muQX9 zp-gJ7ypFn*zzd^IUTAnw#l%#&ySdr-&D#;>30zN1SWAnWnwnaz$DinU+Rkg=4LQ>hHg4VsdvpW9=O!r7+L%@bDKV_Qn}^j<-TZ2JS%2qTDDcpi7T0GP9wio zDR3_hSaD9-46ktk zCQ63#YYq;p(j8soo?i8^H(|FkX!W9~+H|I`C@JMX7Df%#lmD}Enpiye^=yvmbP&Xt zXi05U&iq9`Tm}pcvoI`Ybp$>#8EN$+JepkHsZT{#3(SYtHR!5ddEnfrkc>uidm#M$ zwG?YUweS*Yu958B?P!J0b9xC#*amz{hB)lbrCW6??E)oJih`gYbdMw&j+Nd(Xx>pt zUiLgl7=a9Lf6|qX}OC+hGa6oP0AXjr!A*{Fu^Gx*!6Uv&+*8 z;LcEL#pzZ2`NtjH#-j&wZ+$QX&{5qR|8=`l2)yl)r}20=o2mEi(!^XT0ul`KRbGEW zh#>gDkfuMN79Y=)H*S5i6Hg+g_Dlqo-Odm<*Mewo(n;dJ zD;#WixSb@kdbU&$jK3jy<8Mx05DYQMQJXSI7u0%OTfWU5K-VYN$1V)N&KH*!cRPjO zxd;6;5xZd|z0Z*Op{d70i(BXK*ZBhJoC`%YSM}g7LCtgBIZx}56H7K#JVbnPax%x+ z&T|JSw}n~-x9vhoM8I(twDR%_d8AO@=wgXfnMUI!ouj>q$_shs`vMW_RaP9<8z1>} zb#2hmMppe@UWT#XR6W@Q-X0J3gZ>A?rYwn|f|$O+psnjQqXd70P4BkW^CRU4WH@_r za{3DSd>(rKaYS1W9e(1AP9&iovcn^y!&q#Sk3&tU)lg|Z9sR2bvgF0(ra1?7zF3)@ zkWD9jdvvt-6=*+uTWZ$M)!X*2ZI-P`CJYVtC9xm7vbw;}CnK_R-+S&~(W zWO*1#C3xPB%}Ptr2xAb@GZu(NL4yd_4=#ghYuS^&eGgyaxEjATpK5cYH)#>@Rkj)( z9T8yF%;;}F^ZU=e*e+sKl#U#y#1v~af6It<8Hl_cqbs&U3_U>9iClQx?(HsX7F&8y zG`SwT?&gg$ztBuok>WS3P)N=TS4_3+Kf$%&nqxJ}Gi z7{)FA|GcO)8~@2<%B@{wG$XHL!+s_frq$xf5(m2vACTU_MFLA+Oigr(@bV%O#;fk0 z%-7eeF;=CtG$5ZT)2PqY8THRzo!YP_7J)YcJ$MD&xJM4cp38*;PYnrC(FVumufdgl z^ATk7NWFWWr`I(e$QUK798UYeFW4otw36xfl4on>-QBnMED(CXx;pz}fwt4>u5d7M zdUhlSkIO-c`naXj{;XeMu<2+T>4O1kYPE?b&)FtDwRX(k!lqKa7^>^SghtVE`k1@sflrsYH7U1d<%(HM0q*m z6+9xJvY678=dk#2mwKAZ{rcOb%l5$@kGS|cJ?I_1g!Fwv+<>y$d6bOFbY*1?h*8V+ z!^;fTt@MaYVS=suA8ZGQ+}q2le-W~t_`H@i!3a)Qj%(FCXd%?Cyq|kSuply zh5f8UEV=I9yT`-IA)opAGs#V0K#1P7Mx9NPXP3w=>o&+BwUjOQ_U7vwW#K#5gPF3e zLTEU&mvsKnjPX~NMYoEA_>wb`gTa<$|?`-OT2ZQf?fmYqrUvx`OQy_ zH?H>k&2C$Znfp?r>mNrS8Xjls{w1oh~MLe`qtc_%+P_U;!9gbK>;ylsR<9l`sin&IzyJ^_EDpq zsp(dFc8DGHZ849hr{h&(6-`GHM@*51E^=mOE;b&vsG!@Gvg)KN=Fi}OZ-MZmOG7iG zD$8DWQc_ZNj_Jf5^TlOg$&-v}BTrL=gtN!)3wdmVT zS5O|;je~H(05EmfK2yA15;PbPc!4)+C8=5$Chr&j$(otWSx zbo4x$a?vDB9X5HD7DK#~)G#koYAUowg8mM7vBpx`0 z(*J2-@ZbsmxWq5e2(#kpY@)0Bn4jQeIbUy=pyNL!x^yd;{8>2l+G(Z@CGz&k&b+p` zeD`$6`ou5H=|ZQ2sv4K8wa&#iiJFNwH#d{`4c1Qy0Th76UJQhRI#3BN@~u@Et4iDqq*o&& zu{tn<3)L$sd;8NL*psF_*|a;X_)klT0v9DX@ntcUaos}0i`Ry|v2@U)DA`{8b|(Es z=<#G}x9h&wjUY3YMq$h9&*Rx?87#1qH}UYW&;ufVpcX}khYt;nJP!HRc?0cI&Ep0u zR!%)^vnr`4Cbx_CB+fc|@*0@U z$j@0k$VzQ&ZXL<-7tzbg%351m1x+dBV5_0rXumS>p7}jn&`tZtpA!7?qxOsa;UU8T zZLY@Cjp2N|Y$>_$#Lv^`@kT~QTyBS-@o|SW2i4oiY)dHm%%_K#dazxJidi@9ij0w; zy9n?FM^Rp~`K3n=!~Q)Skj@3M{QbILd7q{r%TqnWkb~pUfrRYN|C)$MpGab&M}V4RIB-pf zxYmCLUgf{Z8R+kCiXKI^`}2z9@&^o-KYsIb=12r4Xc4bYvuT&Be)r$E5Q*Cdg{`4h z-}#tY3#FV8kdGvILf?L>s)l&fF?(1-puh4nu}=O46R-Z-Ocq1$s_cbIGVJ zjW|0JnZod?t|etFoK1PB7u?w-;lH=!DY^6frLKOfdxDEt#f}hNM{bTFb{C}wO}p*O z|MQos;kP&fAxsY{DMyDedAO9QV&H7J;6c{C@%YmdL^=;Toc~ht_BcX(h_NaS$AzZU zKjFM5l3D(%nAH40?7tzAoVeM`vq$>(3WP=T-nPlGD{o-ZonqPqh)CMC$B_kZ_D9V~ z-(vrJoid)RKBkC*$Lv)S&y5b%Q7ru7s^zo){@%iP$Fo>;F)XRiK8Bx2Sg=zUY4I7O zY2^E;9o|x#iqq9n`EIDLM1M>E_Zx_(FTEH-AZHQh_hLNPl!X}50ldOq+xeempfkvpQ|KHuu^9zc$TH+|MiLaESF^C);0I$&pVdvi-^|i^{i>|bel)H*k zk83&mO5LAmi$3{l(D1LD3Kc$Tl14L(tm)ZL=8ciQ)R;19HsHBotKt+2+5FGZe*YIA z6IAYD5WI%b;y=IsA&m9zao61{R4RJ!=%*!hKOEDTuXEc}zGm2`(`t4ls!xU1Mtb9( zXF&-6)9q~{{DrE1S@ZmUpa@L7mgB$sGEnpLz2D}p;rqe=*){i<3h&$)84dj3KYuC| z4q=GeI`t-nGYlJ*vOoCuMV)V+-`kLr`ixWIKyw_BnFV48<*aO5g1%PQMMo^+Pf?77 zgq{E6@dghq0M;~~`Qlbc|L+%)tWih5B{YhCn=<;YxcLVQP)n0Z?+X7A-7$psnbvNy zqit!2#*{kkpBWbL?WaEao5OANR_A7bmm<^0eaac4evXr_MeZa!%}vvQG^ z`}GPpp@^KA?au#W>no$GTDx#j1QZDc0cjO!0cmMaLb^d(y1N@hKw7%HTROLNcX#Ke zg-yr4?>R@$`R*N;KRO1rSZl8N&Uj+`5pY4xKGR%W3Qc|Y9EbQc^R|&(-Y|HmzdtK? zEO$^;TAI(}_=zPpjuE!K$MJahk0Tiu&a|cPvsJqm^Nk6;?%^|K`ALd3TsFKC z3LQfMN@+lw?|MK@Ig#Boy(C9~P6%C?_Dvp+TawMT;yQ1~J2qUpf8Sp(`0BSsg>Kk3 z>4Zta4s2{-U);k$O*-?0 zQXLNyYTJ|e>fhMOlgQH7dxle2ZgWf&`n>Gr%`2eUIyxp78Hvrr%oL~P=X99$iphxK z&{CkqyHMHO%FZtB)6CeIPZRWe3mG_}^N(ONZELn&Na_{XF z+$KG@BHm{=hsVUk$^#!yQAx?rupn&@bREy=mv4M>KHDzTZVr45zaL{dI07VAK&rK@_g`vnRef#{pw!V`nsN0leP2J_zcUBtgQA` zNB%4IBlfXG7a6;>=M56EG)?pvIe-q6V0up@?+rv$hO;o;hP>SRnbhcw$e+YUS9w>woq`1nxc zd}@Wvtadgf7KYBVsL9c2x?KR8~q#66Al?~1)iwfHZ^tjo(NLK5Ik1^`gB6Y2|0m*Vv6X6z)fsRGVrb@->)7ZODTBP zH#XvLE=La+oA7z<6p}elVW()Fp~(tW1y36g?D*3>K~bM}?*nzT#Y91IKtTRhP3a8^ z&~1m)b(C%IJ0TB9y>0Va8yg^@2pR4=HI~P0B zxffhqu2Toap0}s$`w>Y=f`A~ji1*G#Noli9#1RGK`Pn-3LpbgjRSPsgDF~+0uKFiM zU9eKq*hEHRJ-^r=?h|9MQ16t!GZA?IUJfQYjMXtI3gk_CdU7`zGGETFkY{CQGe1~} zkyTQn=iv#-SNE`>P$QwPczzA%9r^!Otu%zmG=3wp+O@mOhyG-A#p(Hkni=+xQ}mFI zfv&GlO&^8M>+FImT}V20=Is7o&_0#^%>T)>W!CSAvWA+-T~weQ`W|f7Q(pAEK6fAf zCwC)Ulwt`k*WI67?Z#>3?Ml7>U-@){4@Bv+QpIB#JoPO_kX*T3uW#CXe1(Q$$eXwW?gx_{mApk|RTUKVEuZK@y?x(0 z&F|!Ma~4CVb+I-d-#tY-JYPJAkCWj=Nf%sI|hn)gMG z1InRlrCCo5;8h93?->CfMKWGQM4!5oA~baLnOr5M6FfT2{-{JigdD~B>=7|#xg>dc zZTY7X3xq9?=!zw=Th8Vc}D;f z^oXo=CQfHxw*c+fr0(2DpN8)bocXv{g`6-4>j`FuW{*BC6?@ve7|b`w28LS zuGSO~&^`xx+&oQ450JDP?drsM8A!EeEA^mEG~hw98PCFQQ79ddVeu7Ug3H0=cJa;e zkeKJE^9Xxn<6Z7h+{*DUc|E&epEZAv+iQ99TepjCMw|maH>Z6UO%M0=?J{gi>9Pi^ zx_J;8Zq~N&^(*IV4AVuefrngz_kdbncFdi(0E^R=bZpi--19N3@#y-Z4@xBz*l5^& zG0PSmNU&S=Zh2{k6q@`_KqR*}XCPsO13;|Lz!ljcrEt3o4+IkX1qPyOu+)^2R329E zb3KcWLdCS)EK&)TlG0vz%Ah$5SO_h@(*QrO!-4Gzc}naiLvM?er-$PD{o#D-d_dFn z`1unUCQU<3bHQ7Z*%^ZW68_oqZgt}h5hZVV@A%i|K9|HD-(^@TcirceSAiJ9!Owfv zOHEzQ=AFfmc|B~BkI$E)Y<{5Z45w#?6cgX>F7|Zj&ue-93iFPA{zffyIpfR6y9fcD znb7Yq2kT!E|FipypFEzbD( z#Q4NS{tG%f_q$agu{=ODaEFd&Yq$A>|M+Rtt4_bXfbQ-t)!H{06srvo`mx8+zmL665UU4{v^;>6o4hL_1pVT7J5omtcm5 zDtv;NOr-lbi?ZBCHp%A>f-U-VjpO0gP>G9+%ar9Jz$U2H>j70#X@^gTdKCs@Xcmh< ziE)T|tXCf-#S&?Oz0R!}gT zo~&VBR@bDusoa zIrmCeB#hhT0w4rk4FRlU+h-xUPmzStjEaFVEy`zr-3g?1f6rKzOCDw*6F}|@yUZOO z?@hcWdiqo|*Fxi}gVSyOBl8Kov{$+*6AHvz@y_-Zwzk&=n+h5BK0vkc7w(`2)ygSUPsU#!h zf6U$P>1ernu-SQsMd^=mXSffShNmFivK=nuVya<0L<8zRT0Va0rg6YgR285tj%ORz z;lhKahZi2eshyLve(%uQyUl1i@9Aw4NHmv)Q*S9KoINjfOiViAt~cQ1so3hbzg!n< zItRvy{8KT%&u_0A-xR2xrPoVcBPUzeSQ57Di>AED8S2r3%|yEVe=v?tV4G-6Pu5BPyyeUG97WB<%dr34swMlI&dz{S#j_ z#X?23Iya6)F;gQWnYZtu%t&~`!onzLhq)rGWMr{nsls9SkoVnmD38wrmNWWq9g$&& zwjbXA{d(55_H_52fh@7!Eh~R_m*`q>w31MuV>Z> zq}Kt(8x#k!^f$1X6T%t`cC+appwrvj+$<|A6TNI|S(u+!t+DuEF39Zy6rMq0G44E& zP*r_b5u$tuT@iTnj<`mNPX6w!bZ_6?9q1J=0G41X};B~0qeH2eJ;*YP=5l8oj{YDTg2!8#H1IWW+Le>mpp9V-8Ma{&Rk7AFqhpD z>lEWFI2lgPj#bNSvVkTW75p!asU-E-cJbKdgMDXL8U7b%X_&HO00$CJjo`z3itWdgqP zgK$Ngi|r9~LU#OZLg0R0X?eH^T*3AxMX@QlJB!Cr=$RhL zoH^8R25OntoBMOS?3V5}xAUIOUMkFnPEKz6zjMJ0t+{G*Qf`;=$zwio^EYZglW3?D z>0Pdvn}9VgaNm^Y=hj{o{41otgKZCxzyv4L!ScmQ5AZ<|@V4FR&$%+4Dj}I}^4zaK zwK&kKxvSXkUTFiTkb$7jat8OuZ|7TAt(;GbOXRSeBW#Qtir#*V57ISJof{j|m`8l4FXPRB>KEmLt?w9&vF*X^Y z5t=!DjomtQO#5J%&*J^39l|H5J1=S?{+hA=JKVY>WR$;L%FRwbMf1Eb`lqJ@KQxW# zhR=)sbbVU==`Ib5gy)}6dGYZpDdCE!CU`GlK#E|iOnh^m2B2NLyZ65xF&Is4Y&`qj z?9-oASfg??M53v_=hq-tGWH9L`ge5M9+i}omYyCN_k5`NP)Ig_keGPz#%!Y;nZ*-> z({k~qx%mm`C-cAlH!N?qe8Wse#>%P!WQ z#Az2-bsAb@xumKxkc(mt7zTi4tw)2HHRMSlDOtR|{n6S{RN~vet1p^#Sfv6I61j@= zW##xYWEwuPRC4myy1MO;YcH%7$J@aqVdbsrrZUK

m_d$N*^h**QEVDQP}aL|R2IEe7nAwsppI;s@1^0F)MQo3@|1yom>;+#?|ZXW}<1Q>g}M<@s!WRNuQ-C za2p-*i}u*4Ff}Or&uYK-AyTY0zAPI54E4ESRnhSXhwbL&wP)%(>&D^`Ng0{%Ap?E* z%sCtD>y?&E-sZ!ZB11q8#r^X5biVF!GN-)(Es%BJTVEdq4!(dvHIn1|7>|~g_HfDb zXpWtfkkIw<H=WND?(iC7Y|q(gYf8`U7UDauNtLOe>Pr$u1Vvk zUB_DC)~zchIMmv{A^jKn2sf=XI%1Xrix$EN%ar>Qd4!7-x4Gc(=D3~N-01aK` zLT=9U1D>Wo=V15w${CDhddHNDJ_!(~@HwU{4X8Som4Czhop%6RQ|r0N5fi?CmVTcS zomyq(V%^$Kw5fu}^%WXS!ZWP|2CCsyE}f<;oKIyIw;M|Cb+7n%u8*tghZ1nEhoX(d)K5UecyTO-9CSHhsitzhm`|h$c5D z`xhI?Sv`GyCzIBLINDW#z-~*Eg9pwQ4rGGvs{x!~S^H1S*@BcR@5N>eaNvKpT8Uukw)drJ+5Fq3(3d_n;WOV z2(-!!5)^#zrlipoGKAl5~6h$jGX34*e#*ocVP21CoSoPo|@d@h5% zX%x%@Lw)^6X7~iSof`!#AoP`$9e-tzgQwTwaHs2ZvN=_t4{m&=`CK)-(XiJJgGT*y zsTN!mbV!8;Z_oA#O?Qc-keHn-(jU`b%>z2n ztRQ+GK3VA3uU~Iyx5>*Avs(}) zyQ-?rmS}J>X!iGk!kc?=gGM@;(|sVpKFSdY)I!?>bkT0|qoQgF5;%L+6;)I?{(Xh` zi9qZGJhC2tJ2K=v zgZ;BDpiV{LEY*F)W|8x%V_0Hwek;b8465~j!3*~XU5(qp(8H!5ftYEg36p)j{b(5U zieLX_yYs_NLpVl9HB(aKBWT(X>h~<)Uwp8jXD~9*HF8+3sHL@32>$WoEr!T&Hvbjc zMrnd9pbh_dXJnM9j55#?-sj2<`p{!HPUVgx=766+}MLu!v$54L{~I@_1C)%TYrw)b#XxY;58`lUD?UC~DMXDi-meJMWd5yy5PF~aNJQWeLL#H>dzBw_Xj`x&Mrc3 zRNb6RKcpbPC*T)wQGUq_mUmG+Oh<-mAI1B6duXX_6~_yWpHE5#V|@H}krElg{`)6* zJ%7TFsGw7hT5wFGS{}GFY7;0&guglTJvll&J|-!JD3X9QKIINAnE%f#0IMr1G{VnY z6=!TZ@0(=_Jv5&ht+{Di{2_o&QwaJ!=;@_3fY=_g@nj)6i*9IZOWOjUb)F*zlz6_WzVCdE8W?> zi+?YS%>VAn=2dqWE!(U4G{1mgZgz_988o|N4n?|7JlnV5;%*! zw*8cF=Md!gVzmj0ltN=mLJo@%~jB>~PR^V$gN=rQ@E*^67=_xLbmnr$50@ZOOH6W_!iEigs zLm$QU#X^{j#{5E{Azx4bgi#E5!57#)4ybo2(-hV@-h2C&OJg@qrQ{_q@%akjn7X}ziv z-)>R(Hb!}-`Oa0Qy>rum6$N9vBZ|3R&@O%3=8nGOGS>tH#5GE(ou?4c^tDH0Z=Cpd9S_rVm0PQA-X-mHPH;C} zzP${n6S<2fI++T7*+$8@`p#-QD_k^kZ_g}e+(3d5J~h1}kxeOETOiw3KLbtA54iV; zk#{IneXKA;Ev==DY!X(jE%^5I(E7@yJ~;37S97YC>yZEJn(rs_Hf&|K9)=5$f!FDQ z9?nGM>e>T~0>z4}pxmjs8dLYrOG-3oM8mtyi^aEB4u75fwI0S^sp6l8W8E9r0SbD7 zMp9Tfp&Hr4@z<$MR)6TeH%|6Gyz z#;}iO*L-)HdA8dA^dOnA)n`GIw;{jqM3>wjI1xdqlLv!x*{P~?60|>D&v7?(SP(P1 zy*L$)wSeWp;rnRz;>r}9^Cv!S@_p5G(_%Ez&-sq;l25|ZwZceeL`z=~hil3d*x6Pw zaDT2Zu+-xDRA#2B9)-8Dd0%V3H8$bQ#_7ap6BYpLOzYL;Y4|}`sK{DtefpX>VbC}E ziq7hzf~fLlZ%3xAHVN<2qI5iW&NpTnKm!PFv{Ae@LI2{@w!I+t*>ua|0|~bqg%}?o z_b{@I8}@#wJ!E&`8c7WNoers3HLn`AZ(Uq&*zj5Y4n0*VMph1$M?bQ%{}zb z7kN$8!|FfnNE8dK>ejkKE-re^N1qiM4w(<7G>ApJUxl1uKIC+EJ3l|XN2hx3WPD=M zR-YYg6~%W3C=kqJVyD)n4dH?OSFCJs|HL%2)KB-U&$>8sa?p8X`b#R zIPOgQX%?LyCPQ~0ur>a4KS4uxJ^B$~M{g%=r+MFBFq$@2Ej}T^ZimxoV}}k_Z)$3c z%0>2+oPvUw&-th9T`wi(p~ifR8zPkEkF3%7qu3p+OqJhMUnM&ifq@<*xqJBpV zsj7Z8rpt=Bu2B40&*69e=Yz2ArJAnq0`64wM2v3D?bIjJQ3FeSM-857_4PZojBV3* zP|)pT9`HGt7>$4993PoHJ~=7XDrJK|2di$E?QZI7e~pH){v<~43{jdU+lwC#w+_`I zYyM%ys;t+`uz(&d=qpM}_E$_MEg7s5)=u#+qJtz6AN}*@i`isVFfk)pWE9Q!%&@+D z4QuTn1go6#ExkOMw2;`?!vly&{&1GHJKM_sRE@}IneNsO(|m6I*&BetU*Ft3o|U%( zYVL-=MjPQaU;X^bu;Zy&OXTOq%Re*$a0Y5DoPaB-zTS!Y@DsbmVw3&#%Sb-Udf7IY zs9B)z$VgA0(%HGr!19uTGS)Fv1+cnEGw(xQc}gZFhlf)ib!5+LEoa9>N5^y9dw@6k zw$Ksc>Ij{miTGKTrciHso<2T0c_3L+LcHBry+6%h^>N(L!NCFWu{B7~uw=(+_ksll zc~Bm#FW^V?Ddv1k#_S>madAF3SgXr*{V8EF6f%`l)$t=-zTUwYzPhoS;x25y z&}id50aLM!J=-2J-qT{<-&>MOcvm2BJ8Mt)N$$D(8O&pBw)i%XW#^&KcH^YpLMZLa$%VvU(;AU~d;ew~l=3aCcCOstu z1u2h*!^tF10>KVA9>Wf_bg<$=0%H?sTKFM%P$Z7rtW$B%JezHsAEIc;b_ zrl*}yJul}H<0oM-m_eWBqQ_ozsm5H?@oL;RQr8h2W;Ujq5zmXTJL+Pk@39PTTL+2h z6cy_fK1vULM%=Ewa1u+6zd>R_ZK@6aE>28LES@Wh#3{nSz&EB!F)pg7$C5p?=e-@g z-S`!~$7L&>U?SwFhx7jaTFt^$^N8+N;JeHWW0Qg=HwSqkp?J={1q)Ug5 zYz&$|GivDF>vW7~jz`w;z%839Su$TJn1SVcvKr67c=^&BIW;08A|^)I`sOJ87HsS~ zg9+YqC5*qFoEX^*A^oSTSe{}5^^rG}d6&IA?I|ej@6V{<6B)NercvwYS~lgBv)zFH50b#;)$G`9M$a`p3s94>Ym^F(OlIMx(Rd zI|;rf`*L{a9o1K%kB@IGB!m>0?yQD*--ol(@+8w!!<;So{2WtEQc`~8?bCC5Umt(T zXVuiNS&EK=`X1JgE9B?oykcMw(M>D&7Kom6B=LZ!u5oLqlQp~8H3 z2b6#SptP3U=0CexbwNl=MK%0<`q`pMOF@5;gs{YF(^8ggJ0I%r29Hl0${fTd`*A=) z^%Ei}SGy&|W0apYmXw{Ad^kVg!{^;OjJJ(R;qo+}?HAf*SCzkAlJA`TS(_XgdA(O> zZYS|3woov_Rv;8H4>X^%Rq`qRtaOHef{NI@*hCSXh&TllQTa!*R0+U8 zDjgO-Yj?O<)~qC!N-6bRWuZ19Dr$U?c=v9myub=GYRkkV&(tVSR`7ZR+L0ITGe6G* z*gsLRv4)o4sh+?&8*g?`m|92vK5b16Tmp-d8k;36Hs6SU{J1x2{!pW*IqmzP1`1x> z-J9VtLpIz2LQMSm*tQj*ZQZrjM|d|@R^~3Q2IU+>(rR#dss>%Zq2}Q5)qIFrM9t?8 zKP!vR5BPD{)<#yS$o$z*4NqV>NSwN&Sv=WOyeC_|KRmB^%G0Z36?`qWS7I%KmkUW+wr*HsJ6a7dD-AMEd>QMi1YSiG|j6w!`Za#uID?m zd9plgk1ZAoE(=)Ipvgmv2NA;uHkUz>GKgAQ@CDbflm@F1WMRsVZqxU`4PYc8(>5C!+`>ZWLy`DpFkN~R&k!8Ikv-F41s zpJBgdL|k0^!!ACg=z$0EuYNx(VUxx$Ov=j??mP=cMSI`6spEI-D%<%@vFfY?kp+_dGeiwM)`n_?)Xb{^{PUe^j! z6I}hdw7oBAN%LnI^7Z@Y-l*t_`?Q6ZzPmtiT-O}pU zR_|zNdPhdeg01X~&T2tIR!ty?I*WPn>P>?4ngOFX(Byj{?XD;@A}dq6dD{_9Z5pK_ zA}sW{5iGJsK|kVKT3lZb%tLGp41PU+CsVH8F5Xsp6r{E+2T=R%e)i(9Lbhd_=zJA# zA!Yz;xrlv2{iQm_K*Ed&((wH0V4lFPL#pN+lfHxrdn3yQOI_Qsd*v z_gZ82KTGUPN(cOs4#50F*6`pt-C=jMsl@Z-6J8qrH18%6$E1mvFuK($VEdO~`rXci z(g#1Z_sHln_n+l%>KW!48+Qo@I*L?XTzqYfM#?Z$8X5cks3SIATPWKsN(eWZ_k=Xz z%loHzD!7j|Ue(LAjvBrfNcYp$P;vH!jWcPorGFdi=~u4Rgdx2Wlt{%FU?}+^p8Wm$ zr&_soSp3n!r*7$K{A>zJY8%A}>|V1Rs}-TPOXW~0&~R6iq5B}WfoTL;4=s(z<-h3T zCk1a1jU4jP1LGcN^_vY$6iz{9SJCPX1`OtN zC@Q)ED@w2<`n5(0)<Y>N}v%sY9r zhvPF0X=IQ!%E{A#0up?^hxx8+IK3_3qca#_SNm}aX+db>F=(d0&lCC;<; zrpEEF-LUoNA0k!J9tz<3(?8Y7%Sa>_bW&TR%w?ozcWZhEQlrY|TLbvj?>!NF6Yz>IOq(Bm@J#9sdf zHSidWraG$odj^BiPg(M`S1(86y#tRI+7`Nts=s8&DSZ0aA?>TQUSPDdBYP#$_PO^V z#CJPH(30}sSCh6B;cB75k&TUkl)H9FOQjc$la-bHMcOhc*Wn^WSydHmvwneX2k1uI zVbHP8kn2JK)3aRqN%!gP(9~3{Ih#joyDXWAv5ARBqm#h<)vjVZLN+tI)%G6au{#GV ztF(5v`PyH9kM7Nc0I+j!e}8i*H8vrk=6jyEcS~<{Ay_zLKUr=9%0R%M*J8Hv*KAc` zrSb7PHJNbe=+xLb4ECwU0whG8B{B^DH{l+Gs-0kvU3DMQ#CXI2o=z0+SjW>ccR9Q7 z!Q4~b{WlF=%E&Z=!m2wpVN$bKepeHcU@+8sgIg=qD=8@z7!-U2S2AE=hd49IuWg6? zi5mX!URtjlDhJqhxbLnwA7(v*qM{-`z6uRcX#>m7HyZW*gM;+1U+clP8Ka&#LPrDG z(4W7xx~)eKBjw|CJp-E&ci_wd(o@HruZF6ssAvz^X!M%21mO(~Jbj|F(jL7qo3iU0(|Np>#Ppj>Y)0SvLbSxPz(ugn&&kr;P2c;BB6boZ~g~Tb~ zgMpiyRg_Xh(wD3}AprrJO&(-(DLWPA6%L1s_@t!pt5Z{RbMver8AcGx(_ac+o%r`j zK6-fiW<_H;4P{<73!m1+Ar{Ik7p-c%gEb17I&`13>-0 zQwZ3fB_>Ck8=kxDPMXuHR<6^X{~1+->>&|9t%k6e&u{^s2>;d1<&4m%L zUY%?W0mN5tZ!3EK@7x6bIgZ*uGum9rA5frjA*uZ5Sd3C)-e4djYn$rI1?#pw`M^vd zEJby7kgA~pwzqTDReGt_#$z!xqA!KZ>&R_cz~pMm1z3k-HD1W$4rZV#k?ITo!SGORELtexSWrpfT}2P z&eH&EJD7W9WTZ$4!R674&jGm4apOSLh|O|rvRI9ncqx^~^=_h&9pZATS!uKaa4&x{ zBe?Kx%9bd?z!Yk)ocoqM+o=(}Cm+SdK@s2H)y1r{YEuUgUqJg(0kDfs0fM75jPx8J zNF53r8@Xc(u}DZdn-5#ZE30#J8)_RKpjjz;?A$y?{+uSZ8#$R1h=392I_;j0I7?tO#etFJ697>3XP;z|e*<8ri6|11^|`156l1+C=+ z#d}1E{$2|NF}k`0JVph7p=jg~&_%axegiEb+>;yLIZ%01{V)c^gS=W0Pv@{Un)TARovd2H9Io=PC3heZ7-I$3iVYP z$e734#{T+JEcg9q_@ZGlh={uKCs!UnQ_$A?0LpW)w|8LRH%KterWITbpNe8;LKH6w zil-sMav0vT_1N(6{8Gz)eqOMx0N`MdNPqtt8cOh&@kM4}Df<@s0cx%jm5-8~lB|r3 z&a##q(M=2P-HI4HqR|6DN*-QO2nRHW|WLW79V?C(Jb zyapJvv5ARK*M9*fVmp9oGwTCN5$dNey)L5S?pT1%-Lgf2sLnI+QLhK+f|tAy*QbcO_RH zw}fP&IJC-e9($Lv0h6hclg$MbVWLK6MLD^hnF`05gI3Q|L2h5B^uj{d-7^RVG3RKu zftVm{BvjoI;=J^GI~;}hcR)3z1Cl_g)&g+;iYuQiT|(${*hfL%W4Bo!X3P|+t#hYt z(tX5YcG10wODAaTym8zifOsXB?#vvtLMDtmy#s(Ac>>7*b*Xb5Z&>w$j0d6^WPm$B zkj!JdGrXb;D0Ka$UmbG@5)%59ir&m=JkW%o4yS2nTBf7`FZA1+ndr;n6}H5`p7D|E zhre7`k7${gnZew0F{{VZad+~zXACb@ePQMbNYW8=xU612ZlF`E0T3AZfdtmwL{QMq z$x2Bb-1znh!MN?FAMRXs4sZe7jiG7(fay}*_2=WL{Dp>dr>ni}-K|ogJznSIrQNAw zz?aUn0rm+-Mn+FV06FV)c_oro+0yP{G`cuF9USYSbYTQMF|lTBmKN5Ry{GZB+`S| z*SJs z0|{zY?~(xSX12-We9zas=?*dO1~1_(L(*=(-hQ_%Gds5DGzi7KSS}kCau7<&JG$E; z^^sDe-of=~n_BT;9-=HOTlQ@v@S{-Q=k|ocJ`3R+$YID&WBKaxK+!hQ26N@buvGi` zi9C-*TB_14wsY7NE}{WF1RqFIzi~lRx63&BY9CaJJQ8Z682s3dOS_9X$YTsw9hT^R z9HcqW2{AZOwPufT8DlBxV0&xPXe|f0t^dpdhAqCFo{&$y_bYBp%ZsQX;y&eY>M`DN znD7y#IIK<@g&6E>I?Z@4sth3~_ZdL`248v|{|$~qmDM*f5ktqu?oB3M1enKpp{3>*l$0W$YH)Gs0PdgH zbrMD%gg01`P+DrqAFb6?FQ3y-V!EF&u~+s$PDUoJd$dnHE1U8P2A!+7Pwa`LFk7m& zpDB;tE6YP6*3hW-P5_drcRQ#GboBBWMe5w!rPVNQBCX zNyNRnyEaxKGNr~|B0u=Ch2B#aWMBGNAcuZitj0Dw+qgHHPYhRjBn%jFKIR6-GmCR` zro&#m;LsM2p<}Qb1~#+|n&oDzS=4*fUwwULu?FU5=QD%=h*kuRbUs}p5hP7&(%jy` zi;leKKuQhXyr2piEyK@$bdji!738`+~%}5+w*P) za4Lghhpx|dr4JvN$N+W`s8aFp49_G!e0YzHu`Pax!Z`+*b)(OPgNb+?2m8}~P-G$i zeyg?>FSnWAw@cC-v{O0zkB|LQZ;6ONYf3~<`45e$3 zcy46(rzKn)&v1)AnQK_Q;;>npGbX9=hHuWHNVBd{*T330KYyRg4vS6osi>G($R}62 z;oF50>rE+4X&Ed!veGEWa_mV@4{PVXW*W9FHndMxui<*H#|soP(=M0CHwCna-;I{D zCOQTk!CkECh0LbUN#tvAwpBD$7MkaE;Om{Cj$y&-j&!_CMsrq~FT&1=yGnA33pgi0 z{BB#B!tba+g5#I`dRlPm%)ou=S-hX?gkG*(zFaFawSNI97NRU9O!7w+Urn_*htG zCI(Xay?Va((-7A%P;ftZ@WAbQ6AD}Tu+|9=D*>riUQVKm(|R@T$3me}AubSjh>!32 zmZqCak4d_SiGkq)U-Vwp08n3Ty4~@7aX!#_L`FyJo0`fCrUGVP&m}k-gA0|F<(22E zY(?x8#sMdX*TXKovEhjR87?K|#;q0@BmJ--d)0clSSQ(Y43(#Zaz2~B+M9{|wbsdE zJPK>c%*A8SC`{&4CGmH(^hYNajAdbGr+oXu3sRqaez0dZ016sHq7+uPkwc8ud5_P0jSd50!^DH%^99HH@D-S}tXr6HYwj z8cv)l^{8yL?VF!(&H@mf~Dyii9b;z*uS})=AYhP4| zF11At+cRcNcNgG4uMqU6D^;0Uj8z!P;&pfuK}=Q|9f6y zzOCQD@vsAh_Vo6S@>Mi>!U0gU524vI5KDrusd4CCM<%QSkb4(3m#A2>n1t%V=?V@! zz`O!_Tj_aMBW);EyW;^N0l!Xh2>9iV=ISNq?ja(}fd(bob7k{>7Z%m)cb|Y+k(?Y2 zC1oNtM#$M{$78dZuDQOn;Za;}KgB}8VP(=O0P@|br3{w!>>4Q8kqHt3?Kcfrb`o|` zMMYj*{PhhDlBsM$piCX#E~Au6fllASMQZ>bbaaDOwaO$poPmO(lr}Pfb>afs=d86er8t*_%7@-5HLPt#T;_P2a|NS13u&k?JxC0*wLnu4%K5nP_-6V!X~{x( zl@x{xl(?9heawZ?GrmA7Lw001=r}@)6%;0vWMr#2w>k*pPS#HT%P9Q%ItB)l+2VMC zDZsS~EYW}(0gx!z+}b+d9wEE)%KQXM92n+Zt(yeLnoZp^Owh+if7ZHm19*1{U)q5m z_j+Z#>pB6HG^(mh-`)MT7FbJiLm)sE0%^65nq04iKlwjhSsCAJ@wwg` zo1Z7r?!x-!F(H#-XlAxf<`%&UH-gSFRTt%!!j&%aR&{i7aGpJ9lqD!BE^c!zC@$XL zxeA~*#lpgJzdCch+oMKGfN`xHr6Xnvhvmz*y?*h+%lxhDAomqPnn=xHrTszUg^S}oV*-0KHlVBG-Sc| z@z!4?uBZw*l5cn7Q3(m7CFbH+N{UfuAg5?8EFi-e-tEWIzu}RP8~}JR$tkzoQ-_>q zt7P{-K$?h>CX<@vL?sQEGq7{<>@lre$*4P2PG6+(zL$t!6nM+a?NyjP9GUPWIXvd4`&VmKn|~Tp8T`+WFg~Z1r@`s~J{T+-z$ohwP(48}4#qH0+pR%a zK`yiDw@(j?Ujw*;UiWw7v7FQG5#8P>>b0&gP@-w~%6Ekl2VFE=XT&Eaj!`r7eK7Vz zmjNoijsJ(Yw~nfEjow93#6T1SM3C5u(jg@!AqYq}NJ~kBgmfwhf`GsRq`SL21nKTB z>F!$8oosdQ{kwOZ^UodUF!tDEsId6fx4!p%=X~Z9Fzy=SBOHc2I^>26I%pj5ZzjEk zM3KNP-Qnh=+N^7*??pZ=h^V}_5?&$))f`1OFjph*ywh7O*DKlEv(&6VtqT(HC1h9sspV3!xz4k| zr_NvzsgV`wapevPJNr>v*uXTYNG!cdK*92}e8ZtskG)7jwLT_Br6RqSnF>@{Od^h$ zlmu-<<&(ipX`3v!B=@qivQM89v&U}SNb6=s7cs4|SHYGo5DA^BD4PlF6EG>yh|i>K zn$k*0`h>KPwc`8O9=D}x@R{B_YLQ{>xLoxp25N-l(P;B=YPPtGXL&Ph4rUG!QAK#+ zMXAN{@iI{*M`_GUjeqyn$2I5V+M6&WQUPCrgUxC9^uZ0l2N2n#0yi#lcZrDT)2QZx7-FY)(Y)N`8`-RKj{Q*O$(5{$;;|Iz zdG7}UIlF$hZ^NFq)AD^_APKr-h(R^12Ngnt!Oz(W(>|eD5nN+#$YEVi_NVX=F;xEO-A{A9j%%)dD zdI$+^u3xvdKf%Mse!n-$=Xu@cy0gU8k4?>_4&`X%qgdX4@8tnVzO&xiVP%_0aS{hd z^iAQB0aCFDm7=!=*#!c?Q=FNdSyii&J~4So6U%o!gGw>q;+=)#_FApKHmH(Az6Ax< zkJ#?Drl{BQkCvSsAlul-$5qRlp^J{H%6HP+PE|cYq6PJhR~mV_#?Kt1c|G2Cq{+|L zZSq)zy#rA_PL0Ja{n~zcZWrenC|oU`nD^Ady!WlpVQn$XT+H#> z;aoV@-Jn~z$BT7!HagGeA}t5f`W~|judJJRV*i{yo;lcRDl@`S-Z5e@oEn-vIXDw> zd9OJVpZZ?0y=sydQ=2IQiqqc*Li!gSBb4LIBBBO%wxwQW!tbJqh$~6jhQZm`vpd)E z1PT2)Oj&51kgZh(uyD#OSML-DPN+GZ@ZolrIgws7W5Ea8|APY}r}`222+YmRp<_8Y z+J~W3w$lw!Jw!snlY}==8o0Q)Ae{4B9Dqp>VJRaopCpPyqkQ%Hb;u{v8_w4Yq>v?R z&(6!!oPPt#*(hXFV`DPRS0Ee_yf#M1(3Dk0McV+7eSnMGMb5&`UgZ?E-?3N^MmV~i zlK>Y}D;37SYlE-)`cFnChK8esMoQp-1|FbSu3Q;*qgd`slh1oAx>Ut&hd1MKn;1-e z_~|OZD=4B4uGVHiXi_1s*75Y1HSh)o1{gs+jL6E!$RMM{L_tWMAlsC=SYKU@QWpH4 zGXj?l}oNkZfG% zM5EfL1P?pDd)!%eW@b{LD9!pbj-5-NTUUwuqjYYoc?mb=^N_-sS~S1h3m|d_gvx9& zP~WSFo57Ox;&lB|ekY(PoH5ArBJ4KKW-%tZQ~=n1!9qnjgAE;E(h;;@+h`YU>nDT4e)Ob~#LSROMo(;e!IWLWrRrKM8k z!s;~G$(8W2f;kt0UAplcsq+l0vTrKey^Gciin(j(=&>TK6ciwrGwH-f*9SQG7Zwox z0t8HsyGz)07xHn?3M~F&U^p*7`Ch)1NEDg6n9z!KYg?R9Yim2jk61v;@MLSYl#YrDSFfrq^Ba)X)}6Po_ji0N~G88|}D5+P4LYuH-L z_porKQJ13HeJ)zy;Na*B63a_VZ}08V{7lyyL_{AR9(JkTB^8UOU>aQf~> z^mAxd+}*F>+~)S$C4sc3EvG$U2%?uoXiBClSjS+x2z0c!19YTui5wqitHI|Y!*We- zuBX~e=~atIeE1%Y^H`klnWvH4E)M8%uesq_ zVf%22%ed+A~D(N|H0{o~2+sD(<+2G;6#2|{yCY=s1ipopxjD~>K*f>)u0i2}4 z_e`xIz$xNJv&YcIRX*Iz*jNo0$*#)N)6;TtJ()QpD0XJux)5qTUkB;yHW?p-yCfd= zlVQVLZd4DypiH?3BO+nV(+oM@qN<0I^(gwnFIXx|yYWQvUG>b2W? zOqe8GSNAqIORUz%Vbi9jqSD%;J7h?)fe=AnbvoI-#U7o>Y8R;QVNF17iQP}?UVHnQ zN#-CIl(VnX9TugIPxdEZ9md>09|4x{gphB&K6d)re$SJ|z!98zoRB-@+Wn}PG4364Y zSy_pA0kzp-cY-ilzZjSa8g|8^*_D;YLa(_8>B;^5&z?UI&-m=^ov`jncIN%%OKVfp z=ElaPQEW5Bs0=57Y7kMK`_N=}sSo$zLlbb*nXPejLPD;YLdzbj9ZM21ieurIZ zW@cnWL|Yk?hC1V8p%E~`YUMQQPsf#hRMTF{%}{z(Z5zf15*wm8-&u#&6zKdwhEI2AVQB7|mJmX@c3`R6B$87OM+f9Q`g61F~6l zcR^obqYdGaoi}G94YZNPo}`|K3*`%>PkLcoiNSr?(t37qGUZG4g8AvMA)&KS{Lg;p zOr;{i0ItoDlM=n2d#N^CGdZs#^7VT5YTSfnKwg|sb!Js4B`%)jbanwgdi0w&6O%;2 zR01r!Tu_ff?i|iX83C^b^~&Deer|dB`KAD!@+2%i4hN*x_ls$djLp^FxWd)I(Dydl zCWbQ$G=A;jtUWQj?u3VfLd`y~|BLCF9qp|yrhNR!+ZCZ)qTV^>rI+}oj zU~C6E*d@#3gH6Omowsjce&8DM5&oo^nlwE(GXn*&&v?hh?dXmuE=mdtI2`05J-`-< zoPwevX5vuz9N}nszcQF3og{|XmLfCM(UE^?hh9dGlb8)9N0^vPg|9}_RdxfyrEoDL z_&ys3y1YCX&kte#Gt9;k{y=^Oijh*=UF6q?9}j{j7lsQ)KHp6O0|lPN?ZKRBGUv#r zQ?#b23y{4i-x3vTzc#7>5>!KNSUONz(^)J`GMlLONCUG+PVPF!ja{KjicKHy%7wta3zs;tVVmoI+uj+wBqTm=|`kTK~sT*`PZ;BQ1@X zn8bEk5}k^eIN;m2My36snwk&vx(^1IHYE{fF&(wm60*xKe$>H!4Xs=71iv^ySbd`?PYc54T}J!<DSbvXa*rbJCmbD-KBA0HpcRH?99HwFnjc~=|~R^C{JU6jx4!h(pT_0;VxTiwp+ zhXniEI{TL5U&Bfzi*BIynumv{sauD{iKob8kpZk)snhzNUW#PmVk2gw{a1>rky4Bj zN~Kgd1AG!0a6ihrGwPBp9GnUE_3%X6A$LCe`GEnCjqndgNYUJyE$3r}>6RICCj}JH zpk(jtfuMxp!Sd)Dc$UCZ;QS6AZqKKrrENc&Jlw{iQOqCg>Qe7Z#ipQ04W?D=>Fk{3 zf@N|dpQQ?}JzY4oo+U+LP;%PZUe-1TKS1CJczymH0$c}g_t*{f+D|z5ADU#rD@k-% zS{8z{n^K`6TA!}LGSDGhEP)3xmnOdlwlXG=dye`Sy}SKC^Y`kk7}z1+9v&Sr9OlK~ zZUVumv!S73V1OB%r(m+)8T}m?Hy19PVy#HE3v&&j(G1Q6JLZ~WLx2@*bcC3`Su%1G z5`&dv!=0T^pFg+nPand%lBHPSzXV70+tzOh>8;*AK5u>d5=BQ;%J#xpOhpD2yUonD zU=?_JdagpwEpRl@CS(L_AFx?`_3{#i&H)Ph%b0{b*XR>E(D)mHxj^b2g(;n`)x3UONAvhvUPE9ra+V;=?FC&IczzuAp`HV5DdqApyGXOenNnzozNU274 z{T=vi^4i+k_bN1DG6~QKa(~^#PHPI|C*s?zK~*MmMitS1K`MH3%c*&7d1_ln{+uW@nxSMx zalUa`a+%HCN814m18y1R-b%Dot^Q3E3D;4xQpw-^0&X;l;3q8S#KEH`UzLcVVOw_M z%JGV$&W@>Cf#PEOSb>qkAbfJMbD(H!bEc_>R4hDIwc-nL0dz0VLig{pqGvjt+x;nowB)Ns8HcRPEfoAWLm`cURkWnmVaP zNjB)`+)V;1_^0U1%u3VgxuW%PsJ*@ZAxoenhc`Q3-boZys`nufaI5nQmI1kWQU5j& z$l!64&0XwptyrGSR_7fomgDE217{ML)y`$iJ$$$s^;u&Fp}4fPWVte^H`_c*Djpf# z4E27V5|nj%20#Y_ysUPHwvEp4z~jpPy1To3SC7fWbC~N{A8z%vg%y<+7ats6YxIMe z27qd-7Xtwx`RwJj+M9yPZXR-D^w9kW*5}$OnGD6%gUz^|WW|Eih_U5|yq}Cli~n_= zM@e>VW^smX_(4Jk7Mog$nGHB(Vevzw2?t+ftPY9E+P06ssME8jPj&m#4^L0*0M)BY zE4M%FcD{gGqMTV&Brj(v2fGtFC-{q;BAHA|=1)(qNEGAWy&Di234SxgqN1Xjn$u8q z=N^%ekc@%{2P}#2-(LXPEl;Nd&g`s+3{mUxavc&H8ctGDow-(A7`}16o0OQSte|J$ zQ$#0br25h#tJj;X{^reOvFS9p4-O$O5@QwGO~8a@W$3(&fTCeWbaU<|EhtQ)_+cp@AXQqE`-?dp1oul_jDYHd6S3|;%u z#ARf9T~3Z*XR_VY7_VsqN*O+Ezd08NQ4ZZ`)~!a6wFoSr8Z@Kq~w^e#FIXU$8V z4Wd3Pw^r|geglY?P`*yBN7ZOhrjr<9|Spj)fe9?rQ7aA+9wy8XdqY*JFgxaL=^ z`!P?UiUfM+0(drzS2|Q#t|H;!-s;Er&%LU)0mp?Tne8 zp7tVqNWAls1q>({<7?vFJk|eWdv%{~mR_Xit&xff0WOO3S*lvq&=mnY=(>JwE{^EG z&&6izYd(-KJ?Fk1+jK&3!b_PdM}|Kn z#Ys%!tmtTf+GowQXJ_t{U0>AGgMlI}`xJ6=@RCplSAkmu=YEJa8+}-Rzu@sWBU8bb zRC%3f5lKWAAEwc2Hh4xVK<<&;M$ZM^(RHbf2OKL!TLSGUm7U)#jhEXbws;DjFz{bo-MqnBCz!2-@NhMTXm zzh6E2;t4tqzQMl)D{j6?vl0xMXtk*iAUOVW8=O7=q9kqLMnhuLumny1`P*}Z187tK z{_%e}DI8#%mQcV!iH`2s+QHo*E8X+eAIa)r>Q!f4}2H zDXDPdF(kBm!^4~oI}1U1c^`em0t=1U86>W$UuNWfQtRgzAS)3RB>NRyJyA9cTAG?$ zMZ^Wg1zVe6Y5sa6+>A?0=lpfB{++0@V>s-I($tJg`83u%oBGUXSV~DL_|6i1YWwSI zN%4aybK3Wp)=O<=_fsqQ0$#~DUS6W&CP^PBq@7daZf@2b5yNEc;wMVd6G%9Sp z-@o5AH_JUaE>~6_2fxO=u$ftGNG?!J@O)ut*t5XJR!Lf#^5Mg&>4yD$d6y|rCo&uKhqA?Z-NMG6S~y^%q4|{Z7;a-Uy`)UvPkr1* ziqyXxE+=Cx#0e3-Mh7NilAGO5^<`qKdCxy#i=Z;<=IDkXwdfU+Tvcy|J%fq4Q8FRt^-4 zu$8M~ z>v(>HYVOgKCqp@!;sg;CX#9|hTNcXHwrDXr$|)%~USduw*d!FNtN{;8LQHxLDRojc zm^UEyEBp`^8WvZ7ufe*ewl;^|C7Zmr8OsAEJib4EToM;A%2HD?-|9*P)e2a+kvPrK z*A+ldTi4@_rvR+Gv4)0#8U<9;xPyb&`kK1BA~*2yS2&(mN*sZGBinmC3G~*rc6x?1 zxW#8%v&87pi+Ur45x@n_aC97x;$oLpZ~U4AR1So5PZyU1a&mSz@Q!+FFaiNJIJuEV zlvMf(e46z1;VrTRPv2as>o3owr|*v9tPnsG3itLl(AU*PRx4}x5st;n1n1c;8f zXTQIO?Qo+1=~Ew>95DBvxMf>fij(8{czLN0q({33*JulAf`1b{%fyd(c6Ttyzx4O_ zCtwY>trG9XrG)HXNr5^N%$Vao1O?qZ0f*dq%;*%IW^qKs`>ll!IB7n?`d6*%88U8DhsP*pYNo&404Iu>^i33TAiohga$ zmwi@9Qe&pDi}6lRIkA3V;xUF^T(0JJvh{==t66Hiw8N7E&=<3v7xlKCzgB+T&vz^k z0UQ#7`~Car&O0;Pk-Yi8G&KWYsY^PnkAEazO&|-}QuZ_$5(zm#I>u4GR;$tvq(EYI zoR(<`j8i0n9nIpR&DlLo={W>K>$FzVQ8Xnd`xP@Ya}u|U1#A^Qe5lcXu@e&m;G}53 zdNzT%t7suFCB^kq!O|M+)gRcJ_-Kbtd|Vp}M9ZWY<=xBGOzwha}OwBTo(ExmK+ON=^`jg5`n(L5G&4~dEj z2M`UajyhG5$WNuE$lJGLR>m$4g|tJxr@gIf$!P{C`q>nurS|nPF)`-H#csW&8Au!O z@Y$X9^2(k{NuFsd-`heW=e%!lXv^Es;Id`8x>`4<6X355%_z#say)#P$<2@|A}nlk zdh8M(uLaMp_ZR)n&+eZt(*<7m<#=$<%LL_^WW)5=V?-wRW^x}^x>TshcgopD+0^^c zDDl5^O^`AR=dw`{?{Jn<uz#-Ko7`7uB*0uG4hIi()KG;`J#tP|mw25X69W%qT6!xJLs|pk zBHEB>XufVw;$6NOMMXCF&drSj9vj9i7gtxUBry(c?OE_`3yh2u8*uesf;IbVNnCq1 zcUEu}20s71i+gVEK>INq%2mlwEFc$cZ*4s|9h+ZOQX=7!NQ^FoPa2ES-OWv+A}8mX ziGbRK3E;v>7K0NL!5Od@J8aDuFZUBD=4Z!eChI&1Yd{N{jMg1#U(<`@zi08%77rhP zW2w*U(I)}HeRoWg2h4>FL*^*&7iMQwi;RgA^g*EDQ28pUK(L)Qe|M#}N!4RL6(A3;SCn34;fr0A* zlugd)PwM>qWP3%#L_BwPUx|6>P<(wP&nMi$Ey+jA!AilNCYAZ%ceGQWA`j1pdlwhb zU!K=h%^c3gBmMN0lqNPNH{CT&Od3#7j)%w`e6C*mjB!(o0v~)KI=h*B`+I~xW2*ly zk|^X}zAO$Ze1?kcM#Hk57ifYq26n>Gk8DSR&E68&X=9*NM+wQjV1f>)<5iT+!U9Cv zu%gMP*Zn?)v8jORPsJ!xB!qprnMg&ybP}>tDlahBwGs1U)MDs5NAXBW<;u0;5k{)Y z^h?Okzl*OSew6auegox*dHn+~4=!DZ4DcgIR`x2~-I!&W7=erM+0#co`ju2Sx?d$> zYsWp@J6c-$^-up8VMWKHp1l(CHCeQya(M2 z?gRPYugTdXmKS8?_+@YSuH?OKVK|NK%(B9yAS0)sQDP~o&^F+==P0vMrFVKZJM6}6 zq+Ee8GfI4EYq8p!Z^}E@QSIkP`MtCQEQn@jv_f)uH5;qW9{##{)#8)WtJwD__I|M3 zB2ZB+ZEVeo!AD(y5xZKMWo=#E?p)i*PV_~N1fj&2y}i9O%Ec=y$D07I?(Jo*uBd{= zT{DXFI})Z;JG-OY*-)l06%Jd?f=x}LidJk+i+IG999Mi4Ef)blu0^DLM@8lvjeR(j zzIw2g{=ahXAz;tf{>Q%O)dmycuM0h9eBpAzSdCMF|0O(cbQ1gv8r@G4t{-`|I=l@W zxPyQF9#uH|Kyy!z`SzSBpt7-{w!3&3_$&(m-IZA?z+A!mb`RH?VU}cEee?@dz|Mfc zpW|@k1E5`jzP99?!u@I!ZqSdNG(Y)>+)v!<-%VT45%zkEe^Wp~aB=TMz$!CxB;O(U zWZCM$0M$0;RVj(DM7>#7Li$UUybWud)-`()dHlOWJ)}LVP(bR?DzjR$nb27+Wt()Y zO((W$Z4Kvw^Xvgob;wxqrgcvBaXT`HT7#Ws+qDn!RXPb6HR zy4Myq)Sg>_h@Xi#^0i#$@`tUKI&EPoU7<2rZ~7A`6M{3xo?EO~7#q_>XiB{ENKIXG z9_M%z8=I+IuI%W{SDYeU;?ZdwK&uWF?NG))(Chwei#*tKw#b1;&Op}0!PG}D z@I(QbQ)_GM5R%v3XJxb`tb0SJLzRV%?Ho!YNB{vQsIDZqo;}+m=KrFBLP5%^01r(0 z#AM~fNy;r;Y*Fn8N6e6nBGcI`5ggd2)bYZtg`hKu)WM6vWV6{fs?u>Drggx&zLARUyrdgQUcPX z>#D$@wq8&32c8WFcOOgw268GY`*oi-!=oxvp9icKlP<)hNgXPUvT~foc45G4kbd;} zvmjVTn)D_U1`>^z6>Il+Hg;wu7U)Zq2+v!xTcs15jmG+8;`R-VD^t z#bsq&wmT9^O7nmM78X8(gC_p5?TAh3%<3O3pm5dEu@bs#Z4`SFIl&v;N=;T1#X_Ygt~hds6UNz{pDT%Ev1^*REnH=FzQZ;d7Qc(sicsEHaIJ z39qtW{kSbaAz?OLB`!{3eRxpnu>0<4NswzXB{ue=z*56{LTh>}0wGgauAa7=)L|^6 zD^W!gAvV(P;O`%>sAp@7jHwtYS{)4z36vch)IFJ7h1{a9ID@E%U357smA%&z`g)yj zW;D-ADcc{7*V?{sRVvaQPZ@~r%zmdoO?1m*f4F4q$TvG67)>>3iNEi|N8WWV+t9GE zGQ&0!w8L^H1bJiR;rJ39uWha(uw<*bkl(&ob56Y?kc*fH2WDfet8R3BvNo67zYn(`K+zjbt&U zXAWisNUuGjAEpg)Z*geCaVkbQ>?|ca861#b;5*@ruCU(x33w-dvihigQQLCfF53U&Ln`nu6pq$%W6VrxhI zRNO-)p0U{+f2)~hb$o-f{>hbgRaG={Q?rKFB-Rs#ez+LGRTt(U zga_;RoW0Mo>I|CN`IEA4>24UWMG}Q` z{c+7i;o=>-(y6bnPe<2v%tR?SlTk-!xpJSmh}Q51Q}o*}2ag`r0A$bW3$F1{eGay^ zDoaZGH3|D%8l?dZeNRx(Dw*ghvTtl)zzSv&<)TAF7rUQ$hOt{@<1^`FXpcT%Hdf7k z*OeXf5e%~HQDmN-t&Gki>l}{1-PR)<4*S;c9{wA)iWL3hk^hw)B8Ev_Kc0>6S=V= zVsDMZ`b$J~+te#Tp;x(-uF3C8h*YXNc|&Vit$t2szc^twEJ(B+NA|`W6PTYl|0QHS zHp=n#nB#@2s*k80Q*YmH>VnifAHE`BoI+AdKSHkW=nf?I`8lxPBxIl6Yzw<+Ra&@m z=aK6`(raM)5JFdPm?tc6Y^+>0`s2sK_w3I*`R~)_()tY@4i*l<{BiKIg>LEGj=^d| z8zqt2*)(Z;QMRszp|bby<_F~f_Z+T==$54=ykjO{*buN}bJ04G^g4&qJz{wJ^qm=! z2S0SRVQCy1W!<`WVyPNlP^K=h~IYyW{N*&yqgR{o$clS7s z8ZJdnlNc(6M^*yf2_TD!06>{>FyGd4^EGzCL3(`+c1TB^wRecc{f#98T%WT6RbFsY96}x$G2S zT07IavlbwY`655y@uflI`~5wSagyU6%IN-fV69%F4HIgG1MY zv}b6a=i0ZCG-s`=vJ0qv?%L43kA=Lx&R_jdnbQ%v8|moW0&Nr3645eFF3a||Kv~9_ zz9<%(shYaw9W^x1nxRmKD?UW5mL!yvVVQz)i4n!hvp;@3emF1N+jP!jg|BKNFOAIe zJj^dxToV$?;Dk;?lL;j)nCqujUj_=w%1BXFh(cR@{9}GCJUqOSA|+`WDj-Y6bhu;s zK-|Q&o9#+>L2KJTY%4$Cu7ZV)4eBxGgxFenI@C7Wm@FJqMwHd;nSp>VJ*VKN@IrhsM&C;@&o3tyb%3*ETfQ}m3)#jSEI zyE;1&0fAn=cTFP6XPrdD3LpxBsxYCn^4d0ou6}Y-LIUX%((4A%>G3b8600vSE$Q#1 zdE$Jz=T$0%HE;C+tO*@T$*<030dKgsugk~NXUf5BU%}+sjq4K!9b!yOvUnm>;*4lJ zAqpX}w4pDi5di_-RE$aAq~1`AdT)3%#!4HaVOOk25;k4iY!y#vl%=C*I){KJbv&-^ z(G-dT8Jd%2IQYaV{`aot85f)C7X*f?1a$~Ev%{iQaEXA?wiR@iK$5^7e7Tz+xKtN< zp^f*pIIz5HYHD&1)+p*@d%xwbgNMXvnY&~{W~Q;OZt_Avy&ewmJ(iL%=0kXAr9Pm* zGgYWB8<+hRC1(%0i@Gp@LhJn2@dlWS>*=vhaEyM7YHm#T2@lsgN6ENQ{|pij0vDHL zZ(Kcy^pkuR5ZwYzFwazOXz0>tiJZ~!>+xdKlkNHP5d@5K-kgV{CME)I5lrRqc1wQv z2Kt?He-yrMEJmD6tbWz|!wJ=)4^ir3F|~w*a_Qxn=q`L7&wBERp5oaWj;$owwyaE7 zPdD=yj8i?zDJv@{iiTBMES{}%?X8WC0NLlc z)9IHB2dgjn`0ySKfOkk6RaplqVjS8~aK^DULlj0v#?mv>KTiHI@KXZpkQQ+zkRqCI z&L8UYuTx<~{-Cs25O38YBDT<@uc5U8YS#^*WnvQG<$V17;8sSCR3)RLlHuiLV57%a zF5g1FZ1F7mj$;2MY7CPs* zd~=#8rzo47Iru(^PeI0pB3N@Tc)PX+)apM_|GFHM4dJgrev;Ay5M>5$o?LpC5d1PE zW8>n0rUQe+J3lpZ2>(PYp&TO-C8>}ike%I0FCK*p69R1?PDs@v2TzewTUlvo|DGNx z28Ny-vVYt)j@iHiAwB`nZJ0V@NlW>k9NW`3&toFNm=eK(EdJzr34{Z{k)$M}NNd*b z76@GeMZ#eiwlz9RHDrQ^y8dtqx=Oq8YoLu1{UbLo5A-weLXYAeF*KV~E5KFEx^b3v zb?tai#Ck`nf|CUIEm~U4-+fH9e}ERsWN>gmU=xTTFA)8vyB)-x+r?j^?~%R_*%Fh} zzi*-w*7?|j+g9k&`Pjog{MU+^^!;$|HQw0#N?6=S2PN7+4wK#?{CEBA%ys#ky!?=r zhMwVuQwgTT=PrS7oQ=OT9CFbX2U_3ywz&Uq>{!x0&ebHU@za z75EOk?TDNL)yTg;QcaukWxzR63piWu)jJ{XJUXZ!DSE#|khOV$c~_=(3&a%_L6v=p zqr!5P#9dld*yGwmZvOQjS>{%p^PDTR!hByyURszbZ+l&9OfOZ zjoFuXm3zxLMP{Sp$xkHxOt91pb9o*saP z*N5`5;L)L>;d`PBy^`0xHh2i)&A^E4z;0u6Q-8eNEj(NqB65-|0iy=&E*1&Z2auC9 z)T(Gesx>AaLx7v_7SLriGQ24(b9xI(2n*qM?kR$*%+HyQHL~ zl~xmgWq<-+XV;e56Dj=6%3*Q>e(QE+Tx|^$O zCk}<-kMy*(quphBWacc)!S`X&0J{NVhd@A(YzDk8k<$ru!->j>VRjZ4&>YAqDu%9l z-ei6^Sq*>)(B6A`fd2?N>!wS+DHayU18`S}2bmt+^%pN*026O!^~pv&8P+N2p@5qR z$~tj(&1JCquv!_MT3QlnI)E!p##QQg;2Rt~0POLhC#JBJbgRo9U||l?23_(2s(Fh{ zG{fp>$u<~3>I#76Q7w#eM~nTKDTJof;3=hV2d%NT+)l zwZM~10pbxIJ1IK@gV$<6w>pxXHcMjiHGB)2KJ2=K7e{zuhU9Wtri1H_jt(i_wX#

uMgy_#~MI*kl?MI!NISOsZY= z>1qv`ABaB)>jOSf`|fhQo>EjN-fiqZ9RdaX1VA&LihM+v&;V)2|INE*PLwIk500lA zotx6TuG*??V&=RNn3fR7d9k5!k;Yh#@ge^&EY(p+`?kOr<|n9&={x_Cu3?^w-BFAm z;+xmEcDG2Pn8cmz?ou(x#asRQl)`9Meun0f->2d^7?eY7ii^; z;^N+#ux{s0HnWVHM!GB1&@{n8$OH8Fm7MEX0MV6vxN!^1HAhewPzMG2*LV>DD;S`} zk3D0;W_0y?#vb}XKo(Z$H1YjYCYyW^(|Q@m(-~~IAU}Bl2K(aSo|brB20t9&&IdCL zkmNAP{D5wY=me&oLE@Q9Pt%8*=}qa*Y-Ptd04(%|TqOvruu?L$$?Ed_8U%F<8 zm{>B}CyZ)5bnskjaP1bECru(X$y?Mhr}ZX}`alR`GU@`|1~bzk%|iVg!GwM;&B6gQ z^ZrKZvQDQKx(y=D2&0;0UXMqatn9gTD^A7avQe#qp%^n2*m-^mXw>3;(@1SZ5M?XGV7nj7dY5n@SiyNIK}Z;PFuN@&uc7^( z^tR}TPDFyJA^r^J(?RH^A}J9mq)NE!&Sy`QCC{Bg`5=)`vQcJA7E!0G8nUg*?(exI zN;&|yy)_(P%}~woDG#+`p_wXP!N9H7_3vC5k@{(wCbVU>(VE@8G%lC7wk@vNxdWyT#y5m=RZ{h)(p^ET<4aNWn3>|&n4P*lhz(pA zcp+TXEg})g<<*-$a2v37)uHWax^ghOCYKtn=2b@lReQzjn9L z{=*R(#!x`Qdg@yZNf4k4MZ|;ZMbw?^KqQ=kqauoi9&<*ZQ)y-h&!pJu_+OM8I2pMB zBZlJOV>Av>*#pl7!X#1au&hM`yZH!e9n>bReVlL~BS1kt!X$#cnJJ*D83BCkS71!e zt>t@5nibbJ{;61&SQUr+dc$TWR-}!LE-&vO98#Wf6&`?+W4@P$t{yqD(X#_IAE z_bIJL9Zq5N5&@kQrkQ(~B9~Hno8-Zk71pp4@<;BEJlNxEaXIE>?P+b#XV$D25nvSuUun;NZ%6c2PN z9urTy*X%gA>aLggKWiz?E~gpLSD`H)%o$A#D^>+A2~@iIfPldaB-Wgn(F$}f_o_9% z{D}J8A?E7AnT{cHudod|xtqB5089Nu9);&|1Vx-!L?Pn+npCTC6pseUC*li2y=@-9 z>JwmIlQUR(C0{81vP zt!+>&!0_z_4~y4`Q-+2(0S-^-9nf1f!l2bd+C0-e_)L|-7;%}crGF^}N{an>h)qM$ zq^-g)yQyzC*~5g5k&wAEK8hr3jC<-dbktW+Y=aV(QH+syw0hkbjLD$N3?T zWX=}$2d8sXS{~UOnC-ErQqhoR?Xmi?HXd>ZZvxVPPzL1B;q5~oZq!Y)Aa(>FNurI5Xls--&eNh89e!6h~xf<;MTpau?KpX?@da}b*+ zyZV$e@>u18WMst4U<#U1^6cgt$IQ4|3g|CI>i3^*Vo=*%h*bda_Wf1m0xXAg#e@wV zbZ<{fltq2mkpVje+Zj-FBt2 z<&*5=QnFcS!$GUbmgkx1tc;4n3=d~8)VF8j)on6t*h@4l2b&uiT1vJ%Q6c?f+ zF6_)9%4aLlt;&6vNao@SFS#$2y6&HAv1^S6qwZoyD*r)-vv`|^nFyyLzngjmAm?Zo zJEu`o4Uo9+YRVidTUa)~`Q`>@1Ww^;qh;298#MkyPYY7k>)x+*!3*~r&DuxiUHkvF zg?{jI0Uhx7w(}W>8+z}pqXE%gDTpD-1xY5c)rddAwJkaq4l|~m0;JcJ*Ph4+~KvEXYlsI3!Cld#;9{3Fp%dTnWKeTXtQS{)7$_f z_6i*3#u0`L1qC}(&+TrYY_OJ&zlacU8bUD*O!*}{I4Fp?LqTb9@QaugVfw|g#S0Mj ziCMPLKHwq}1vEvSk;41tFgtF4P&?pNzaZ;mEWvcIQeCi+H+&Dd3!*{=l-S4x2^8*) z^yYJNOwA<%J6Ek|JTt!BSOO~Rge*>_5y2h=|10VgKtEw$Mxj`!lV#RT##%o?bTRzpY;6A9(qk?2Qd8o@F;cNR}od?EJ0l@8%c?EtnRmz; z_O}4XH@e42=q(Rg#35Houba9VEK3{kp%|O(P>sU26ClE(LARxs>skgLh8AO){X)YF zOJlchEJArRL>VT=1l;h*JhOwGDFVFrH}Rz?KzN|i6{@TO2wS)v0mfAogcAuE2sAhm zM7skln}8#?ZVe$wQ@gHCJaAd_2_q_2#%P7T>%Vn7yAyfrBx_5#!d#q%8~i=ah9n4%+Q0YkXEN`X{SWd*LwhFt4So=eR^InCvo7t2ua^y zV|vAHfio%tZ*$BZK~O45%2RI0`!mzx^MmNBKImNz%uH$iBRJCSCF z_KXD~p~)z0SSF+@Z_K<0G~N<7K9X|Q$(SC7+70r$;Sg)D zFnC&C6d=ka*}lGN)7{`xiSAbx;dd&e0f+jBlJwtVk$E#s7CkrC#mmuJCZ|uI5EFHK zb7TslZwl1|=Bi7kp54Myogsu_gv@eW&efkHLE8MQ$8`QR6SnitZ2oicVy?M=n~Ervj)s1?u&ryv_%jk>p+OQ|ZaY0N$}rWRm~gp&4tlUOVg&;x_EuN!;}x zJ_fy&48wdZ@=+}xb2T?bd+H-YQ;zs&7Z?*}f28cc5g6UN7AW%{YElQ(%@AE11O zsFe1$Ewb{4&6lmKM>-WOv~}ap830vc%_sT6f!;72j>_Re)`FIVNaguB^k288pFb~ zFx({uaUUcS?gUdV+%Ixp`9&6?cwK{|aMFIX)-ei zO7Z;L+=mdP%^}-*QgqE&)EPsYeW}g4Zg}vUHhQ(VOPgY>$2==xz$^rO$;HdN6{_j2 zCpUY=Lp^SCXGOGCW^}XHGBo9h6QY#u0C&uuh^5?JHH{@*=7KWLo!Jbp1C1*?HKE-g zerfrcq2G{Mee~F|CWo|?gl5mHb%(ja47rlUMcYS`? z4M_Qo-teI@laX#oepb`$bw?>tO}LJ*BMmNx98R8y4s642FI(KkfNW8ewc#g7Hyb_J zQM^q3t9$in*+`M&4vQG;DKj6@!Z{AqiK_pT!(M;qsk#mty+{NMyuVzrew&y8@1rYa z;jRP83lYm~_(tzeQ~BdAm<2h5EbDOR_7_QceW#JDhov%}|4iQ&2w!q`;-dG@Wi-|4 zPK^MSnqA6`5PUbjJn$axo7$*-M~g>DL{Mlbrop<6FYX7WkSqEdQmrZ7VYT@h_%)SC zc?BEVB@6Q;bU8#uz4u@8PT|V1U)pWish`&QGdP0M;TH@5xKw3w;F_8HRH~<%kmrXi zofm&!bbj+BG*sB==Y{~q%`@Vg2i`U&fBt-=O>*7octaVBx)0wLMb0)8trzNRgZT+- z4c7HyD6>sCmkzdl*iX(-VKC!_%ZRWee7>IXxFS_JQ&PAime4V)tZv+P@%t-=hCgoK zuBvG5P&w;CR8h1qD?;c{%&gyIp)=rTgPh$x!rCgS`Bo-(pYAs9L&NY`L17d+d*tVk zG*1?!z>17-?`xn|SDBl$549k7f@7fWOa@Z~MwoVJ6=&GyeBXilc}g3enKyoh%2&>l4ver?}^^qkek;G$iqPTq`{! zF7C0=i+J`dt1%=IyTzwEG;xJm0E>WHe_8BYop?JyThfED9hCUnube(y&pQ^PdjG+L z6L~XnFESt>e5CX>R3TSCUE3&(=9sc5xix6(N-c=2k3K5rOf-sd-SVSQ36LE9c3l($(*{u}j#1(+eeQthtQTk9TMzNLPmhmLb@O9lHgD!kDqZ<9*1|pr%V{@s zDas?CjKe9MYG7+p?a!x%ODZ83>obczy_E9Q=d}8pP>ANgO+k_y6J>E!GeY9jt1-w3 zV|F+~tHP%?_1vH(FSj^A6zk_IF!p%0{^LPgq(Gr!9s}BzCi`UH*Cb3u#Qf`ZbV`h_eUj0OMcK#XtS2En%l&^+^>$GH|hEd z$;CJ^B+n$AbAeA3=;zzOGsP1%@?B4iu%>FA{7^hUtKN_ptxxZO5@m?>7Nwoz3Z@-|YPhTBVIEv8Jtor20w zO-Y6XvixE9+Z5W+-6hn=*$k^EY7`DAgVh>KIpYy-tq!#LX>a)k0kTj01ZeI|DOE8 zYL(WO};Cs)Y8NTraW-d_KNzP0|qfj&cSQM$k+mpW zPvvhYng~IWtI*|FPbtOSEJwGpG(Vy!rPXdiyK6R+yi)d~X5O^IvKjvg=|o z;vJngAo;&0*WrJP>gB)xL%48ka=FeM!V2*j{v`VG1@q*2mZmV4TcAUqH}A*+t^JAW H7jFJ11AA?C literal 112258 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%0A4xI<5 z(a)c8jxFf{i1OnJx>efGuoy1gxvMV@--t>p*mSESG`xwu&4ti{e}0FU$?wr;m-ZT> zOI>ATmVS4h!?1?~lRuDe4wND|!Ke&sWZ3+5;jD{538^7z$~vs}xyNNk%Ex!FW9KX_&Gb z%JlpmG(Le@B+RI7gBtCnuCXzXcEcB_LX-QjVvm)Ii>p)ltJTOi-z z9Z&|ho=q+`9~WVjt`4y)drsvY2NE|5p-!|^|XDmwm%F}L9t$t*U$1;A!cwpA}kWw z2Vdv!^@+jUfZW{m&qPN*RDp3Z zJhD!x+Yk;895xI06_!5Y5aqCHX=t>?JpBMyg$9j{HXaFwB}fCG;{hd-rc#v00h(ny zJ)gPf^dXw;kZI8I2~&)#ki6&T|Fd$SFE;Fc@zNv|(CBxXL--ESoHi2J;>e3v@7`YC z20JGzVN?iX^w^I&GJ(cOs!qA2ah1s9Bel&FWM9{quq;oLMDQ01(Mf>}ifU0pLV_dY z77>w7U7#Ll*8O?v=Kx~?gy@@av@1vNM_(=^sKH@*d1$5{7(78?15k@(WDs#rTbp!C zC0La)w*gducmDhonB>7ig=Ke-%HK{fD_ye@06VC^WOUF#ye?+N-FhNQM2QH-HZd`& zO-$H@s|?^V;L~B!{ktTGCvU83JV~iE$d`oU5~*V>_OeW~`rYSoDgvey7otRdGW=p5 zM~r;jn|VIKQ2WS6*K5YsE;J4|?R}i*o1$+~io5M-Xpy#A}mtb#haz zpa%fXI?$Yg`N9__EzcDe2zjl)Aw@LkWn2t<6O)TfMUi8)E0Rz%Iaeo8(Q3z`DjUqi zdfDX^CnNNXT@z6ih?#Arwl11l z|G@lW60WyPpfIhtj}xFw7mLWD+H3-q5Jw6rs3|wdz^GUQicP$>9tBRH-(7f!dEWQR`WO0=j=-08HiMZ!Zu$}{P*X}z$I z^dU~cJ;Ed7X@Ix^E_nK^I-zhX7>7?4r6@kN4CYzAaj7cSlYkKymy?he7$Z-1=7zWb*nSjaGK+&U>coPY>kL$A38p*_es- zmu2V`_;)t;@bs~-V)sRHRNToP0*j1QSB&4wqF1W<6y9#}IL$sM06h){v#yriT_XjLO2 zA))#ZtSouLQGLbU11|X)>QnL2>oAw4F2)2kFULSz?J+Kdb?2HZIor|K#A+rxPQ@{QOz`SAysb7)LV=$f^UV z-Va=M!P6hCB4yrOhh8df2%7-B9Xi|`T&dj-sn5AjJ*3U}0EcA3zzy*B)}&V{bU`A~ zFtI+!WMXzU9Dw(w>Fh#5fh)(W{M$C^3Co5=WUtu|cuqh82uE^!_VP+;Fdi(CQd>gsXfTN;_T^dD6 zqtm!a(eJoJ67ATF_~kB@QM#=d%jc?IWkebY=a(QE!l5}P7A$Q{dUF&+L_`kp&LzeG z+EY`XLLe{2oy;|G!kavK=E7sc%_q@3YG6HYlf!~Yw^(gNI$)OF@VM7r14#(!Yyb>j z1{eN_x9U9*1FJr|O|h$$VkiW?-EmM+^h&9lbJ-|YTZlqL3>js6AD6o2_a97Jb*Vr$ zHVa3bEBlaRkrs5+;^$8Pf8!Z&NZ?@palemhbH$;Irltxq%k z=#nWr7>f|pMJzS`c#~-dL0SV@5fP3wT!3`caL4;L%s032*P}fl&2qdaC!2}p@7k_fvGc& zBd#~1Y$rma_ZRnw2;I;#1G7z>i#+o=E98Qu3x%_i?Bnh72Zm53b{jD7rRR+s$#o7j z^V$R`Y_MrJHcUDSEV`1S9jW0of_@4*sXt#JrF(w3koTEFP0p-64p+gT)AkEtD+#LE zC4<+#nr36L)ppLbO~2U=RF)b@floIbH%A1aqTC8ma~yQsbR*$mgYgzNgL)w_h6)^f z^9;~U$w_;mPkA@wM{lUUP1ZpTLi?Rs(FQsx%1-^jq?MPWT`A|S5m0r281nA1P4De2 z9&f0P`H7pHd9Z-N99M8((%;|TVq8QaQ~i04TSYmH0KTtMXt|@LkfllcBBmVjkyhkl zcWko`jHm+6&-3>y@Lgvy>K!{={@oX8X$v-LE==vKB`1gP32YM+M6p z{KNM*wS1y{1fIEHJbo=mD-K?Ao54SBQ&dRE{qXghAw3XLG0|T20y6c2RG!avel?tt z@>z^49X-6l;c^ORZ6|h0HOob+mSjP}ofqe`$nx)SBw4NrL{A~dq0bHr%k*~UIp&>u z9?9r7SMaux z?~cRCiaegk-M=q;Evea=y5T|~ar43J7dsnd+V@G#e);Y0;E4&>UYqyeuv)ka{cO*a z=TkCp_x5=XS9&)=D2sFH_KX3C<>v5@N?gu`{L%Q5)uqbMK3pr`+;?XSE3{gh?DHDU ztX%%f;EI~f?x}E`W=xo153e3x30AKh>PN&v1CA29kROAqxNw~q^W;uW_TDf4u z@F9!+j5og|edNo#hnKqN!K8(S=u`-*+;SsxoNAk_Psu3d7;EW67feRkrv}VIi5HS9QnVJZE;mzZuzaQ+(7w#A@-Cc zwvw27G&a^79bu|+xMqpF{o}-@!VJEnw^r(b?z}|8K?w(rPLx%r9KW0PobQ(}Z-)@* zuJ1A$po2^{on&sI084u98Kn>RE0QvUmlS7>W3Jt&+7BG~`l!EDMhCO?Ww2$!grA zeAl3keaqWnYx3(OTn^cT)h7@3|sp-}(+>}?d6GkVe z;(d5H;82R~8xK(L z*B!=4!o!T}TwVk6Obu0t@~tL-MhIDr)!CZ3k#)~+s1!G9H`3B7F+yO>gdVr<-XiGfpCVc$E|?`AMCZM z!QF(AFfs@T*x1aBZ#9jX~?hz2|L-jnHZeGX?fEyxFZ` zBVSoYkEQ+;Wlh`7=C)t*F}Nsv= z>z%{-j877MYh|CPA*^yQL+b=LhsN?Ms>o)xQzP7A>*qP5k`)oJz1?%#^}(>ZoJ{&R zM_`2Hf@xEin#uB5fFx`PZkmV}GcAH-wzFwSsQrV#e1TqE7eHTuA1zO93JN7QJZe(nu+gj zd;63|U#pV*!o_uXJ#4<`V|vsErwB4GaflI7AC{!J4?^cCTr}0o=zU11Z-PhecSXnO z`E%SBKRY8?QxOO8#`%;#R@g3`OVx_{!If;<{5bQsnl<}ZJUY@f{&M{*l61~LBIhsP zII5=p{{*%F$(#7W0Rkr}^m(@m3)l9w1HgEB=3oNThT@m6kaK2kd}i&u4>9L(LzR=( zIh?SB5P)9fU0SJU97^1)qoe2B^`uMhUtg+cD1vsTm7)cU@gNx`fWB{mrpaz5ISIwN zh*7ajm!8DMW;uK&8%*QZi7h6ZN|vi{5z;+}zVuhqp8#Oo8}FXYC>wzq; zg29V`ZqZrWRuk%g7K)3RXTNx|U{Y4EdAQV+6-ETcnlD$~u$gX!`fVDveinynq`F%9ITOfWtRM@=il}ba*?SoDF4iRt2G_ z`$(lp@p5&y79U^5de_kA)+Be9=GJNrn2`W!Q-O``r226#AJ$&%^6-bx*BKQ6?~4gH z{tkKdcbG?2ytl1{*jXb`!l^6A3+yg^k%T!sH9L(nfRs{+_^Ol)drpwv|ay z8tn5L?zQGhh>19>E=oXH*pB(R{k=0xzXMNL{*EZJ-u-H~KC2#mhif*q4hoa`p)xh0 zI2&$5;3)#AjSogL0S2|bPPCdzGJcE&jsa?}70jx5<#M+M7;!5tuA=Op9WKhbXWA+!NI>1>2!JGtt4(uf9OZSL z{?bAT@~595sSNxrUB+fvN8JHz4sbAxK_bA%hcUP9F+XT-aJsJc!Qanve^%;BsezH0;stOl61CdH>HUDRczGe0NgB znqQkFFJfg(Z?szczWk424IdWo4mGEe=V^+ppGi1J7+ayj(JQ$9wliepj9B=^!ZIC8Gyv5)ye(_(wF#VlhP2H)&2Q zR{fwk$c3Ox1wr?+3xP=y_Q zqv8^tKLm+UZ_d3wlQNZDeHmT1RY*1oz1ND+{nCK`pO8*!+MJ5_1{T-n8vkesx)6&kE@!6SmEjJ!->nC zYbg?YxXw0dAlj_yL_-7h0QyyiqY+HusvHMy4N?H2B3SF|GwlVVa47{Fz2GgBx;YkL z94l#V4jxiui3tfRPP%hyazYM{T= zUH?TC5;)C|79k9gFraJ@uuFi`0^p=LEIMlbU3BzEK5}i zwKCO#qJ=`5XDD`yM5wl@@*3FVfz4W*=NyL9SX@Melu6UHD?M7XI6OEwPn_cXqi8GH zgafMp__`DV4mOa(Q2d$LBSc6v$ZV#5@OD?35bH1GM^EV17vs=HZ|VL1^SKPI_IS0O z%PklsJvVxW;IVO!gT@HK4P)g;ZyGBO*D%`;tt>1K5Sx)X^(OwIz$9b=SME#$ z0x{J*5)Wm0Q}n*l264{;#_#|GH2`eFSqNy>yMYS>Wx4<~pU?eAGc&9d*l39}H&)uM&XhWm zcjCsbR*iCu35iLFL#1bAk@~hBnNfXf5wp$Dc9?73ekA1nhmoFsp793BV)ECoWBj@`L@aKw9CvoP`UtkunUHyMbSLxfQk*~ zS$qUB=#LTa-%{le45AL0=H%ISl)cLPZ}{mBU|F{DlEq9@4~)JXMpm|R%~GGs{tCN! zTy|eIEX{hp>2D$O$krOpDA^4D*dRRIRzfFrH!?0?ulG7A?T3ec9tGw9R>9(TmERQZ45cg~KOe508U zajXk51gm52x1;dQH9sGGDQEay?_!1AISnSmQsLsoJ!MSC*_>hmi} z5!+)QKBKrw)DItVIj_}4?^P5#vL^sVNlE$4Om;F+X)%ARQ@#jQzUL}Rx;1@+`zWio z!cy5AlXePaOEXV+#97+rIFiH8Z@&I=x|hMd|1v!=u=^6kTbvNy&*4mnwawY|@102ofVCqgQW$nnNW?jD5|+oWDjK4# zrgC(*QC>Qjm8bPKD-*Q@o|UDIB-N)-XL+jdd5?H3~ zJx%hd3ue!(FCyXF%~n-w*czW~ew$O*Qq?J5JVmi?^Cl^OG8ETjpcN zcJVZRt~Cv^zg?c5)K_t;^vWnR-`Bv4l>aW~COd!lP@Eg?)7FjIp%-^53^H5_W8ER;qzO;x6- zTHGYhsAI|_tv=x#g2l4Gi-M`Cf2PDHELWG*KrYR8w@!x6DRN&)H(CnDXNc&06hIGh z!(`9!U%yois>5TeHGptD%4K3+#4 z60~Pl7nny@d}DAc+z(L2{;P*@ou+mukF$4G-Oq1i0$nK8!Z}ZKnqYb< z%#=kFmqFLGDKtP95J>8;tM>WwxYZvB?J)Ykt@d})Dk4i(1ywka`g_|hZ{qFnruq`> zk(mV5he*t4ypNJmMBrIzFhA%`82dVwT3ZV|kz_`yQW=AecLe#D!75JVZ1Y~u zYSRV3H5NJ5-GTB9HIt3MN3L(E*7mjLB41zM%lLy2M{8WI!|?{g+3jW51W8F|Qo2&H z_003_f3nM*y+lGhQ$wNzrXzPaBPQQlq!3HZ{Rp@xhcTNOGgU~J=`o7R65q!mV#Tmo z)lDY_NoGVi>TkifGa@iGiGT6#{ly#fg(Xi1e5H}FO*vRQ9J3Sxf>LDvQbwU|ypNot zn73+7OGjpA)Nsf)*4<6CQCrFU^)|P-Ti*6~jx+MMt>pwrvQGpO@a6TzuGZizd=Cfs zxuC46C{}UZXk$U>M&I^Us%H>D4Gx1nldnqVR@Ug*sKvLI3sW-KSJy-cXe8^{#s++N z-mX^3MZI0}i$auHiN9?*#sZ2bJX84G`eueoyl&vqZpf8vr>P(pHqN45A`08hYFy=T zX#etkzIs~Q^laAO(9Vt}+v|Eey-FzVJxli>#)6ISpTi&H&a~LKBIA9y3xDAthl(fA zL;T31TP$z)Izl9Al@|P086BpQYbF`LlvVbW60-jp05-U!r@l-g%65NX9cXvq?X=GM zpsjzvkTZ_}H^a|Q8k$;NN5nQjdPVCn?v?Xa@LF8- z9E1irnA$ zcA57WSo{NVvF#m+Sf>P!uJN`N&);|%5SFWl_pf}Jj3?_ZhA&1rAc zn`Jf1+&ZM;=4{T%Vv%H9MW0rpI{0KPP4jb|M~MYSH8Kq#``Urqn|b!uE~VyV&x+IN3}FXzXDs`T(0abH7$Vcha(z0bJF zC|q4gBie3edbNqusY`=*cP(2asHwZuu~m5dyQ-B{D&p4_!Hq@U2UO$E?luAb{yS^a z2Tik3qwCzIc4g%nZlzXCMOtbB-*>XD?VJ=-vR(H&f-(AV3D_4hMR8 z>%Pk!9S(K8I(Son#77{S*fXuyXSz0K*2lqaOVzPpiyql-+_g}$X3TCe0VNOgkOcrg zhrlc+@Qv5fL_4mv)PQi8SGytqB18Uz&a_v_qntK-V>M(+r8^5dgf{c}lTn4B6uil4 zjR6En0hmg8plC8?yE8@YqCuQt0AF9e2nxB8r@%ZAvzeM!pE)427Q0Mde<_2J3V`JH z^x(;)^|FA*aIPaoXWiiY(UD%qOXJM&BIfmmVGsW(W|i^nbi#z1!!lfSe~#H`;#u@S zG&BdU83VLW#;p6gWE%|#qvK);ntvQBd>DKWO3OBJ7O;FKoV5m`AF02-0i~1m9}g|4 zQG4Wpug07xFItTS*|+rL}25t$TQ_Zj7aDspGgeja)yvvwt~l3qEv4Eo8n#i5K>)2%hc z7Gj6H%-5Fk`92#th2#D%8Y*6bUXV}hV$($UE*pcguIR8<2g(w3J8sW5fpUsu{$JI7 zcT|&k+oq%MSVjdE6$@q1!7kY70xC)o0XrZ93L+{Uq(fo>QIX<^qS8bJtYD@dB zYovx=Lx4b%y&jl(clXTMbM~Kozi-tKHX)!1`>}c)7Yad}RrQ_sGFL zdriQh4#S8o^xcF14G9Qe1&x^RJH_g=La+CFuvxLOK4|q$2OaQs_#=0r?Jk948!!L? zFOD@i(%3Kz-1lroB!!TiL)P`^r@}I}Ig;4`fgXkdeg)ir+bht>Odym#JYvk(!-h2K? zhhEjlOYMmYf_~oMCvWT4)XrymN=|}vb;v4i{F*WlUJo8D5pmRvy<%>f-V~MT0}giJ z*?v=m=juVkMYupN&WblXR?PE?Frq~_>!lM&b zYhVT>`;kSIbpPk~BlA3wv^9`Z_e!bcW)D~P3s`(7WIJ{q}e zu}Bn>`B&N2P^UJi)Q$HCVpJ7-B8k*u4Y`VlxaRTWni|ck#n1y6FiwFH$1aB4^90+Hav1{OmL;w=vkT7eLe+olY|xL2F1vW-RS`kS$4Ew^C;Z60r8bb zNeF{(P9xX6DI5bPw3uQWq0B4fW_=st8V^0_6HA|LEp?x0HvD`kd}mDZ7l>vkBJ?ow zw+Wix@)!1KgRyeg-RVLLYFYO=TxDWVJfmu6IGdMuJF_#8YYHq+gxbSE1>FU^S4@zw%OFfwLUZ>PY1L(l3+%Y zHOhIrLYB=LtU+Mc{)hiMm<}IVO%{>VP^}Z@Jsya6PROGgpk2F)0`tfp z?7#>xtSOhX?*YylO4Y+%3atAXjw%iLnMZ|%h0sYgMF~B`3}}QN!{ev7uLcLl>CczG z0dya9k-EX8{-X*wkuu+<)-q$9DNgOz3(xBD60j|hs69(QUl{=JgwLf9#gNWL0-(_8&1@P)YF2{vV!y{aq3KU+8E4zJiaP zUQNbUoh?h|ard47tGM`2v6lbn(eXS|{1>e+Bk~D;BN^*UTJvV(rfJ3`V8a#(h_Yi7OHcEq^&Gt9K_DuHV#dG91_J(%G}D6ze&j+5}P@ zJ7M)eg1ZDS@hFF)Rs_yt)ihcTRYZ>E3zJtj!2N3mF8x}cuK>U2*oRn2-o2Ox8X>QZ zMS-{ooaRTMdMC};+{pLU|84EA)w#NWt*~Pro5f~`HP}J;)c_e~^R)BqN8J~Z{I4=+ zTe|M&ONUt|1+TJYz<5)Np!c5fSyKju#Z-i!EU2zz<>HMc2jeO-CTez~&M^%e-v&qU zYAp;-*nzYXT&rsbQox@ovbx*xExXFhJ^t0zf%9B`JQsd{Rz{rtMcLg zX5c>l^cpV!xokty)D#Y^sTPXmc&0R~b}2dLK3m<=kQS72k$CU7oV?YMogWk%hF~K^%#u-h7&=Gh;-{OC z*ch9+VMALMDmfLhc@9N|?<#Z}CtmQ~;}J}Szl+fZK_1dIgc{Guz(S4UieOKHO2SpP zW=E+at-mYCj67u$JJI5r^v!+3>xxX`zozpxnjIYb5r;MMR(mKE*iM3Zbt>rk@KB_s ztT6R@1sC*TLo&O1jrPU**V0h89U5qms>Vo3 zh%teKtTC#Aiqn^)^93h8F|PiY>$WR7sAGdAEqW!#VIDMj^t;kEeC}8;<>SY{6D0d! z+CV6YRcI|kxEk)>%VD{VS%0uW)8Q*|@2e4yDCjMj$?%BLZSDlr(&9br0Wb*YybR8DGam zD#<;9Okr4QD|4r#y@z8r=&4Yn$#eDvW;C{Jx$yd%pEX9T@;ybKET^MOusQ>G7Z>+N zg?PTtMt-vZxbj3qE*A**`9^$_8L!G!Uz?ArBDN*jCOcz7QkvDhic(z(CAV7G<+hw9 zl)UGAjm6TtUkhf!%yz8BseJ$wFFn)c&I8i7!59l{beF1AxjWBFy9dc6X=5k(pUK5Ut9F{!G*xP)eLRdP+kQWDUwvLi zcCqvRJWonwS-B-J?|L{HAx?c>K`AA76~hA-?PuZ&UNh@OdE0r zF9w^@R5mY-DCT#@#urFmW-V*{sH+(m5K#5SBnaDB;>Jy~%Lscy@$JQ_{uOE<7M;NY zj`z_v4xGk1fTX-q+;{-f9rDDatT^6|laAk?A6EbC(ds6CVU##@X&5GK7`&(8`cecH zSljoVA2LDAQFiaU1A-{+((OCpneKEbnLQbaww-nmQhu;@2H*Z>=*`6l3Z?@emyT6m#L|$)@?a1q)2i@ ze|9g&8Hq-%qXB17DhA6skNT}lTRrW$gq&IzK{c2?wz-B(n|aNjTNj8J#u#KYFjrnS zr?u#~tZS?wJXvW}Va6FP_&y(O#d9wTbE`1vt=djL*x69Vff~Hg5$?ou$>*X=1aXdV z!F0r=_JXZDpKG~W=kqI^352%7*0ut_gKyvgwBA2s(gvq`KZK)9NS?_;*7Rs&2iLiYpeKBRY`qq#-7|W&Zz@c3I-u?^(KuI^M_j$C7sBsad zvPUh)kTN{W7wmhSb1m%QZo8J&`PJN(BjL{7aoL^~a(t^gUP@RkYaNoPy*P%xCe-%( zJBSaRyTcbb)Not9gwa&gqQZBD)>Gp8=#M*|OO3{(G{WR?KxKRR3GBIKZSKw(OzVCB z0Tfe-47~|k%TF*+pBc77Kyf6e9rE+3WE;N5%(21fW(5r-JpH`&%K{b^vb8)P;Uei$ zk0pGAnbRf4e!J^G)COw2JXnjO9MsXCS!`y~RP8=9q^@Oy+(nK6-{3tv^Xf4}hZav% z=}|+sDErma)NsLE%y8+;qN9&w4`(O)DRR2e-1#=kclaxz?0aUjxhrF}kTwJmXwY!) zItS_D->7P6G((@lj6kI>O!6P_8s>iZhY&&xLUm8v(nnnf#4G7P+x_HFMhru=`P=p} zcqhW(x%g!PXUNWzsG{SwJnuW>*UP0R;Q9#h`Ax)WwjmwnO%T^Uq(c5^){^_M%VKaa zb<98(>Q3}7g;1q?bUWug>WR&$c}?b$R`xHP(_CK~ihR@2kPjL3f;rsf(vaso7h$r; z+eaX3Z#5N2`P())naBf=?T`YuVd3I4#dNS z!{W}+-!np?268G1u7B`Ax5YiF9c5mSw9Q4~U3%rxZXO-yjdjc{Uq~UMB#!xv? zWmu|gMx}4s{%VL#SC(K{)2yy#UV#UWC&3Cj8gUP0;sSJewo47=^@GHPWkDRY=AUCFHNQpHkWmZq#xqcA7~X*=K6;h zl_b{U%coCQd|SkSKLHo!i%cF+=IOI218|>>J4s{3We@oB=P_tadII0pJ z<(|A=_qklyF)7q!E*6UGG_7z8!8>hGqC3VnDo6Mq_nOBVGARSnh!>honlc%L9T+h_ z87Nn~!w3yKnr{{kXmky8;*bJ!=7h>(rG6<-pkp!0jkL13$l++2SBn>NV@d*8N&LtFYBk_o52PtPi&OK$+34G0ME zf9ll=fG^g)&!VUD*^YCm8bOZeQ1+SE4eMFH6I6d@Tp3Do$%XCNLodvo={(Y=M|VTt zvQg6Q_XBy41P!UAyJd^VCtA$7?S5w}K&Zi*pCJI+eWpE&)lVm(j~ zOPI5I#GMO8108y+L=#!l*ob~>9GN-f=fg!$Mxfi`Dd%!5W>Ep@OSyY*aR$>)iP-Su z!*p)+RNK%(Xz2>acqK-tnnp9DGcW@QOAY|Iyo!{4gb2U^BH3|N<-&&VtGt9AARD~& zmVfsJ1{zH?P36TwR0eLzmfD}3MM6&7s^YF{h@E|FZEIUoN5nPo2CAv)9!axq&9d)p zLbKY0M7B_Ori?{n=Eha6FhY$Gb^B<)9pze@>f=pN#M_`e!B6yvC@qwqXd07hI=R`s z0attohS@<}q#oF^;k1{F6D(QeB|cY6r4YJcjjAt8Z;d#K0aa^D{PiberHWJnm2Ade z%Wa7UBnlwu>4<2l!gT-nPmK_@W+GXlbu`4W#pl;bIoCEtE%TM`(wee8Z&1ZNoZC!a zZ}0LoQ&pV)sJB`RHegWzA9)-e<`p}vBO50?u|TmKBQ$`smw;eOb!&#)whsKU+g6kxBdD7k+9 zdTR}E_H@L`U|)GSVAi?OwC+UDn8{)tK0ZFBBx~oKm0r=*({~q6Xa&g*FdMC!;pM`T zTEruO_T}!W2+O8=K8)#D!{+lO)ANN~H@#s3a$LIi=4|aD@U?B-A?k3JI+%=xC_?_+ zTazKzz;9$0hWN^hAXdE(-N(6g;ln6e;y$2NTR9CHn|o}`;F)~?x77mp2sRN zAG7#cx2aRV0QSmY?Tq6M?Wic6vy74-7^W_D4tJdDd6bXHUk0Wq75ILmb`JQX=k|<28+N2!_7ISg9MfQwD~S1C-rqlP@??ER}sE zVzOLis4zQX316NthzF5n&0kE+Mq!EOpkauHXt(ILNDq(rNr+AXaLWy)+eK>xZFsmf z*t$*9J#l>k1k(`oh1!n3>v=ky4d`VrlR;iEmm+;d*=A;O>r(Ob1Bm9a@J*swu3_(n zktU=2wRdbv6btMWsof`uz+GrvTnAWwvp&JS0mJ48?3oXs&43M2NAiNgCv*A3RP>aF zEpb9vfpP*jcdykdqk8oHhZvr5fE}N7<5g+;NJjy85m7Fc zPCpavM;rsFX`XIB)Ad+o1G08R&b}u5KpbKfrZB{g-bLKPw~`;W|JFT}xiNt^>8Gk% zed^RG@DK{@m3T#@$;)2M0h-_LE53=Oh*%ChZp^l&;*oFOoCuOk&gs)sNu`9~I&n~!GF6f`c#SjqL0pP#QdRI6)&dtefE~Fed49rV#q8YsIG{`Ql)<+=l z!XC>q^pb=Kq#QE!o^0Z*f(`g41e*uUC%*!F2y-2*uk-qiD@q(gLB}VhVyVd$|IQ0A z(4R9|E{gZKX4uz|peGI8w}trh%yRTdC<-;TBKHGBJ)|0g@YFaBdB6c1CC%@1VqgsM zY^AW}9kAAAPM+M6P|o4h5Ll`84@I1f?l1ZP zZ0{`>uFK_F5}u7WyK2Bpq_O!jO8{QzD_-LnYGHRnZQzusI-WC(6B>eiolFx#9@s(9C`EI#&Q zu2Z*tFjunX-2SgJ?EI%2qD|YspIybr=O;Hf2}TSMnaM|C96E)Cx=NdO@5XScFyd8@ z)BuSgm=+2dttqd3yw1mrtHr$lgGC#bW5;H&nX>spdRT_8FdK@`mgkq~Z3**%CzGRYkENY2LJAwr>8cZnNZ-Qce?6TnG9# zD=*`vTlZO+mTBwTkE1C8{(TuNYGTSbWX(9nIgj@5XmPVcK!Gh#D0xIcq=gPd1>LwO z0%V#53kC24E^uy|J@@<5(m_z&#V@5u5;w2qkXDmSv%U3!jk9>qkG~Sk%Vo%JWn}obZpx+V?VAGNyxV@?KDo1Kyq$OaL|;0QbwRMz~`$ z7%~X3*CW~iN3ieiS7O?O9c3cvM3qmSy4vR#hH?QP>Uu{(d3ej4LOZbLl;}r7@=;fd zFThMy2aXW5XhAN&VKB!iAB7%>e%M-3Ckk(nboqVnNGUf;P+^4j`%J@?g9@y-O53)G zntWM)h1fAaX;+08m8GeM88f%s&HQ<1sa@xHjFJ5cY)06*;}i<+}l5{75+6Auvo5=OX#DNlp>0qo_xal>4&Sg%v6;Zq}c{2I@ryzLW>W~WoZ#x_j zd<*Zn+)q(ty={lwy*YhK9hG>G`|?5Z&)Z%{+)cG+0vA(dDD7{aXuj7Si_%#*D=!i# zV2*64(2p+NOIaq%Sf&DdeMGZE^*L?A%m&<2M9?7as(r$Z+DGfhlvvF;A>pXp4gTY1 z&%WgwnvzfmuizVU$pUQf5U~>_f#NjKuk=@Ud0++5-qzx1m>qkM$D*p6Q$|qDRJKD0 zs4N0TgGiVt%U)}RiNpN$N0SRU2)?*KFpka`@FPIONbA;3@H=Sb`wHh?<#{m*t%DGo za@}4UNf~XZ9lVOlWd4;8U<}px9cw&L#l7W2OMQml4>V+;B~QWChDcZ>v8JOeFT_2O z{mIjNt;OVKHQwvvVxg1bD@h&0)H0OUxB)%a$iiV2}(u+T~Yysh_a4{2T zo=(QK^4Frr1>)FsC=1r^I{6ua&XgkXdW#P`+@~4`iU|2gXdWENu?Ei3fXX*~<>;Wb zLf3O+qhA;vOUMoz_g_6B%?~mJ!u|hQd$JxtX#bESSW!tw+{Iw=U$;El7^}BOJ;;%= zShihKu-r0jW|ZqO2KHfvFT)59epsjZ%@8Wsix&B}@G*n{5>(DoH^+hA53w^N`NFXo z%vAqg#Dyz-|NLnfIdMilk`@<`PUAF9fivMsKeKSF{%gham-EFc@>d$yVVeScm4FE{fBBpjX}=5}r=m*bo6{b^r& z&d(%4#EBqis^9BB5jq4F!VLOZKW5Glc@pGhAM7#^!wkZA58uT-RoMH`<_Oq5j-wkFo&FRBmMJKLt zqUy9*USGOYaTLKCj$;qFsuiZh5m4}mIij*SLZ5VX*ebe|C@bNWM;Y7&zy^e0QtLX| zo2qEt#FKw!LAP_%b?cR6;Aik2wAC88x+nKTaPU<7JaL1-2-QL6*yUm!li~hJ6t2#g zHWisqf|N*9UC6QFdh~dIeVY3;Z{pBe(vL85=olK~5SQNT&_rCTeqTJ?8gXPx{KuntS#~NtxGeL(Ky@jKNr!IBco%G?H8!j&csV zf}xCB%V`nFG1B^Cw3S$iI@70m(y3#k^T>^z?!1&GQJwBz|)?hy-~ zYsZm&=m(Rh2j%?a6R&`tgfK+>%AlWojnhQfq~F=7A0v&?rLOUwONod6%oRP_e-teu z%z&&w*NYuRfmY}`C*5vC-QKqU1%JyGy`||Fs?lfmMmjrjBhi@`y>fJ# z5C=0m2|sKQ{IJ0?ijk3##}>T-@qi-_a)wBJK~U{*aM-=hu!gK~%O8Jugh?5Zx9fhX z!eRTDPyzOn1}swmXn0_ZD=)7zF<;SL*c(G`ekOjhT65SBg8T5L$zcQV!_mVGdk} zV-?or%)@tCQ0=tVz<4;A5^ecW4>ckZ93gN{2zQ6FK-q_dt*W(t&!sYtC5oBj=ZkRH z<)?az0HG?6zaEE>Rj~0id=fSCNlYFgoPCJgqPgu)$4!Kt^{5)m{l=?spdDVfiUs*y z>55m{Z>?RNF2dtw&dowd=}V0AnB3bKf88Bn2}IpSq$l;C2Qk|i?@WlTuve*_&l=zx zk5N*DgFC~;UB;r}2hM|LYbBon`ZC3GUd2ZrKsM^ zm624ceMoAfIO8NiZX;=i2RaccrmnPF4FUELx@ zTZTZ7uIMm>z3qQ!8|aR|iw<>0bG?vPXf=EK4R>wG%?dRMvzFCGb0WJ1^_dryUS?)1 zyNG6FuxkW*lpMy+c%aKB{9usNWB}ELtGWVEhyQk#-mL;d0 zP`wGd_ESW92FqISLfpsbt4*?_`<{vB(0FQFKN+|V_y88JMN(HeRcA73)_N*wu@AYu zE0ktQg0H`rll#L3D(H&mmASMU0dh9DVggVFDnd&hAwmV*yIz>mT!+}r^$T2}k~H=q z1S}<#)zav)oI*9n9{;TiPz_Tu#!AI7p-0syW8tHeyi)K}C#>#5`x8ys?GA|XV(74D zq&gHQe`3H%zR;=9hrR*mCh9orv+r-_A=~X~aPUFfjshSD5aPz5vp~{5FoCNs>7=YB zTW=1|sCAD4u{p*yngi4y|iu1ecv=o zv1z37rYcQKra4N3oRiA_Vb6J5ln&(P&01mDh|Fx>_8ZkK>TZ4#r!&x+C&fZq z90_{30KBV-Bhn)8*-l5>k2b*jJs?C@%oEcBDgSZhzP>WwYNSJi1&F>w(X!slqpifi zd^+9L%fP8MGRGqayJm}IBMvJi|Ase(`&*r+2c)p4ILK?!I)0pBf?M1tLWqMEq{^sZ zKr9guk&XOChu(Kvy~r_Fiwy|MqMYi-n4|I|+|%c~Ahf8Fd|^*cEPAm*od*_6LPqR7 z(}*M$olygXtA|qylW|JS%_{bglg;Egr z00_GwM(6ZIhhgx`iVt1^DK_mYN{pHQI1OLL%qpl-gw1PCIrG*E>2uVoou;$b;Ji^QFAL!mI|a z-*kF(vxnUN8&w65c6#Eer4l_d5!>-niabtH5iUhf563K(OJcAmr0x$qD94sU1H~=a z?4zVJ(;eYMRJo59&@87M(2HW>kD$4&`QSJK_{11CmYG-Zs49ISazT<>Tq1Acdwg6Aj!zN{G_m*AmTZTEyPQ%}nF~_Q@YY_e55<1wA^`M^Q zhT@TIWcpF44WTTlo3GFi-mRvtzLd+;%2r~dGvIwOiHsf}e` zFFe0{z_bX$8r396`jfl(DRjv8_y3HL55OiF&T2fkY5R60svN;{Hi4nY;r`QN~(XT%lP|ltNPZRp4x1PX*Ln%^sOIOh6~Fme#`TWx)mMjoJ2j!$!CU_F$q%QaI$K27eN}&0#r3t+!fIVp9PQ}xK zJo&*7^y|_talOP{8Q?L)p+QH|sOXykxsA^u!9h$?FOazzgeuNH=U2sJQS}Q_mAw3> zCxqAe{<2`9#tT{ODi=Z0o{Iry>G2qZKlL(RDhY@w?V2L z={^HK{I6f8dX=@f6?7*6?y3DHZ=J@96Hu#HBU%s0_R*Q8HwPLlTGFQ)1?;+h%-NV1 z=v}g1yM8e0PTK3qBbmYUpK3yvv`e zi>1V$i55dfI+B#-?RG0bg<4z|6KY|okEHy=wz;A_(L zu@V5SI3P(yyAzZesCOmzE?4Q^!OMkD`0Z+A&BWRx%#kHGpM zeCz}@&RDX5_AbbVPq^?mbe_n8-|neJguZ6jrihj5E(YhSc6 zX-u@(#L=5HbRv>YX3I_Kzr?;jnd~hKmn`8Xd{R-pZR}&gG}BaXTs07m$VPnHU>#S4 zm>}+HZ1E#JtjeyVM-rU6q!Sf%8cZGaF}gQ>#u zE?|jJ@uQaZBLZ3x($(Chi*IGO&Z|p+yNv@0wQS%M0D|nMdi8tpE@iK7_XGkNw+BV6 zoOXG(vV|ag24uI$6~9TVx%!gZA|^(x$FH1#&vGFMJzeunF$;Y*_lwq~CoRNs_Wy|y z?e?cNWm$9C+|0B8jTJ@AUAIb*+!fCc5(jxg8)hM#VR3&GscA5riI=lgz;~wajCuPE zW)ln(Ef1AzyC2b8V{zcxN!qp85I5T?ghSIlUuN?RoquQBs-;-`Q2KLc;ggA%W|qKN zZCkgU?;nN&Yv47o{c}Jq@H_7@jzdx;o;j%qx}Mt;t2EoD?Gnh0Rxr;Yiz(aXS1+WL$|XQi?)NgKe0| z56g_ZjXn8Ze>$c$+e>uo*4huXb0Sb?#GB?GjDt>uI|vKOllgE>k+93#794g;X=mT@ z#bmNl!EK>=SH?_G!jD+A+Yvjn3v4sD&07nX|3^#)(SqTZkrK2A5S-+nJfk*@TS7ux!^-%e1uNId+eFBzyl4LPmgTx}onGq8qa{7<7 zp+r_!P&n{h;5U)L9c|i4-Bmqzp}tvuy?uXaW>sQwkO*zp=?;I(W?4_Q_vg|sw`NU+ zlT&P?VagZ>DZ1qLr0Y;ZL-9FEzt0LjFK#_Lq=WH0&mZi2b$4{UXYANDq@-|w#=aNHWw2VYR=DKEIf{1iEv? zLYd4eLHhaeCAuJ}PUNR6tB3!{J-ydC6e0-eMsJjVC&a^gFip!dPO@>(891Aam+c4K zk8jhBQ9ccIYu{eu%%zm}8q+_nA`nB0&Mc0{aH*{s?~@5HDdJt2>s6mmr$n(O8|)X?b8ix-h7W%4|^27dW%es^zYx+yKK` z3I^VMLG4sKI!`#8J+aw%=Q$PM8Oe?U)Wy5c^?IOF#tD9qz0?EcL`7Nn0;L$i2Efd+ z!CEqrGd!l=FC;BSA$ofzAp;k0MBuKe*kb4GcpRpHb{=8QXIGJG#!#5-AJo5>=TkI&Id-Ra5ZQM4_4MOs2uRab8$ncLc) zM#$9D9sCYGqpeG}1}vY8cf3Td|1?i_`*s-+kw-HyN`xmLPO6JBP1{ce3{MZ4A&hdR zg~n~|6T#AAHN*fSN?xkH8F|KLMr~`zhOEw5s?ZFLZ;M4saBA^p2Wh<%>lEy|;?HQl zEBo9ULD-Xk7im!K`ziU&B-dszksdlJ*UFW$^w_l@q9aAOa8ka@sXtSsCfCI@H-hg( zeAE*dS(yp71~Y_abwtW2M=CnxyiNJ*UuixpyEOWW<&YK~I3g6X-}E@DD96cjg~tIw z6h29E7?6VlWEJPqXRvBILhe10+N9~?GO)^Cw0Oa&(r)mG_|%#fbI@Wx;HFQUBTq8Rt$vg&k* z3-}VZ4!19rBb%fZ7K-bu;(hgp(Twf9}wg}vG2y=bagJ zKv?!oHjzh4X=Fn_HdxJ%nb*qiSbMyZZAjgEq7>4mQ{*uK^RtJX1yU;X%TTmcg2m((*PmpCEZrhCPv^7~vXaN|aY z?NWznxCNQb^`Ua2qMZ{oZr{Y#nbV$zkH9Kk-9_BKIW;{&*)x&;MqbpAqq8-W!Qyh7 z(7(!t#pfE%Sw^Y3VZq!4TV}xjPjZ?W0t(`C#ar*(!hb9zj=u%-YGQdFScKkoBR;I! MG0mefM=ss@A29{hJpcdz diff --git a/docs/images/prowler-app/slack/disconnect-confirmation.png b/docs/images/prowler-app/slack/disconnect-confirmation.png index 830847e7f75f9171b3b588bd21d03656151f3a16..77e732a8467b43e6ff573d3f7c477afb48b3c2ea 100644 GIT binary patch literal 159397 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%0Aj7!DVeg$!rP);6 z)Ra@@@BSuTK2MpZ6AN};0B9ZV{+5LnzvK+ zq}am$&aw|0oE(nx4w0U~O;2`T9C&DqokhLcbbEaXXt>oZ=a0pMRj86wjbmd#zPlYPNXvL_V0W3oE;Ez@b>vA@>(P#i zS@`L7`}qa|guUCe6Au)il2THcaTS_YE^A1wHul(4nA)88{#T9^RuM#}Df)&(m4 zi(q;fHdhBP>;RX;u&=K#iO0#vXM{_*2^D83-b#OYERN>)$1;4w1x@(snOfy9hG^{T z68g)@R$G71OvCf2tAcSCYo0selb^%VDB7Rg7awH37_BVSAc=O z)BnsW%&&KB*ZErLJiirrvYZM=a><291dteRrjZqZ=Ok5p@9Ww@4D%3wS=R$kKn*Cw$Zb`81}k5@RopF6YiJs+OPoUz==1CCJ_F+)!4r^Kjg~C z#9jz&n9k@kFHkyN_axu{u?Sky5LlR{&w}A<7tRmk1nQ!z>cUqi>^-~tB4QmJkXbpx-e>?XvzcS|1V8WLOx|8X>WVyo&U9AmIR89rsY^tVyK4T`%5T`@r7h zZq1Pp`(r&7Fyl2CSzt_GD87z7+!7g?tW#|+JRJR&$$ZL$q~Kv3x^PhNY)c4+f9B)H ze;?qtpFXSwk<*8-Jbe8v@;_hyjjj8L4f6~g|7<#73;cM$-k-6QeF}XrI-j8f^0fHC z-j1c{r#HQRHlM)%!J$5Uzh90t6MP)zH#Q%NDTOvsMg3y(=NqEF5tjxSj>me;urTih z;2%cOg5PZlJ_l2S)(n^MSny#KRu7{fBNTsF3VZ)d2u$1oLmD1N`=-a8y@4YaV;=wW zxknIi{WE$fxEl;f=_S>th(AM;5DKspTmOmhplT@%KgZCL=JU*_W+;I5l zJYQP`z+56D{00*X^XSR&|wufvwVO7oOz zS5TMNR#v9NkpcundxABr92}CYQIU!hYRa0i`JRf9xw)3_O=ds)VvEJ)hSJso`~!&j zYBCk`rTZvzf9R=Q&SNb0zj$)uII!j9=6m~z`)WF!-*wM10?rLFm^$|Zky-re6 zlKomQLP8FUgTrx=mJ{^I)m*~Pj+%YHzcz}eD7Ijs&S>M{;J5FVyL8JxPmE=201&*S z?dcITUxXh_?ORCq#3!EnITM{hRVwTdoS1J|6p7L}9}hFg!Jb%3_ZH_nW^V%2%o<%| z<>aLQT|}WuLB5fc8iQWd*5#2lysp>%PxCa_<>hP#;dI->We^CI)VZBz$XI|7P{4g6 zIx<03vuyKd?U>C(l3mn0F_GZ-7zc}v>PMkFC`ggV^_fX@%FN+Z>K|u6*4qcKNC4)+ z$&+dei2)x3Lu!9Wic}GGu(?sb#=?CIXv`<`#?SW`6~sg}7}=PaLEQ3zpOTUD9txQ$ zE=EuAy4bvH9qq`9K{Fm?a+vzJ79g>k(9`pnrl6?E2pYL|Rw64GwLH<@-kCtd-u2Ew zzUTB*4wqh2*sU%vuOj;tP$?VC!TzzXDcC=wA^hYImhMv_QY^`K#dLAHr^qj!T7P9{ z-*nQPKM5s>Wq<$C8B-V+-Oco)sfU5baZZsA1&==>QW36BgK1CbrA2$WNtk)1X1aV} z$8vf)?B4jdZ~EJ|P;O1S=cPYL*~w#2t(;S<&L%#8US_wT>5k##n5eBpe@G^L4&b&P z?7RjZ4fu^;B6P8m*(^oQnuQ6kqk4R7MM$3pzcujVlgyozwHT8&{T=UPtj%Tm${jjd zo0Qb>qkre-Mg|Sd$;nBME=2P6^UO=sM;3Q1FWDA94m0sm%*Z(J&kV_EH#+x3oo=Fr z9`-;I*bDo%w^B_jH91vnT^Rn1;WzxBX^8ZBm8ld1TcDj@#-6E}f>bSjyzl7BIsJYAy;2$|r~-+S(1hgdK$0 zp}l(Y7ppxV67navUqt3YB$>0zrNHSl@Z z3ZLc+iNM1Mr9BPFHcVx=HvWO|5@T1=epoS{4{JHCQDS}hpiPj1!uj?pEGQ_*Am}v* zhqIg8OvPM?C^iMu+AZ+yP>hR-+PmrHY>=alj4%Uz82}1gc`gKya$BcYqNuo0F`(2Z zAudixh+k1`YH$B}jKg)S^)p$gH|fnEw$4IK&9;BQWYE|#8Qlw0bb8t*R+B4r_#4>8t zx~bHP(-9NnH+b)#9Y=&lY@zjijwj!O3;7}|%4wXHPLui0PL1)qwDi0~wroNv)lQ_ILm5xw|Lc^bhF786ixH#ZM{ zj0o6Z9DA4D8DU%C>8@`cwl|85!0mg?&41gs9RbnI{5 z=^hPUV-NzBD$kqEZ*AC^m{A#-nK8XokuaJ?g9BM4c=7SulQvW|G$89_$2WOF5*QK@ z*Ta3j%)CU)z&BINLF=~FmGlXDlL;yAye(DlZc8oJtVnfsdK$2+JC&5+#Fi9pW{~ml zn)1AQRbEhFZfl#i2UY460dyQV^qM!TJyC~tN*Pzd!6>C~kFu&_4>9`Ge$3U_t$5!y z-!oFYxLJ;CuJgK`S(A!;0rMGoFzVsKyp{yC>^gyu9Km zVsv8N&FxvvPcD9Z#laDq$blc`>FG(?bZKmA`qd7dd$D@a%f!GSqo`>7{lTfT9pL>m z0(wFu4MQK%+x-}YgaTME7_grW>nj%~3*24WrOSVhPO32M8RcB?INmO4HqR?D;WOEu zC{ioY1(g>E2gv$AJJUFQQLsOX35?#sSGN*qvKQ zUMKVjJaCS3=sQ>$7jPu#I_U^YN%cht-n5`h)l6}XqT4hd58hwR-Y@otLTZd@zFPKB zrh4$P@b&xrM1bRoW^!Y~efz{QiHI1Vn3y;N`svf%RoxXB+Xp}r$@qw^-mA@jbaWJC z@^!%<&-&v>MxG_m;)GONEh@;%lYSF7y~~fHG+Q6?K199J($J{%xD0N-uWy!;ka1m$ zQ3J?=!tn63SMS2NPU2QORLIK=jZ!hp(7VRYA;*;Q0HuflGK<( zqNAhH2xuIRj~sdCGXpRr;t2GTFtTz@ET`+pK|4Za_S*G+b0&hRv9R#+gwY_xr|ySpfn69``>#ilIGkFOnkxt&kFqhn=_!nqr;@se73X2+L%o$Z4D+2va8Sjg32n0=@(8TR-7n-_e(W)?Ex>l?M$CQsRN$#{-M@Q)8aZiJ54_~a1a#%u+1jpKs4>D0vhHngi17=-`L<%*pK^Q3xgahs&gF1*a(TRgf*RtyGbegnD>K_*)Hgi*yDb1iNl7V! zkiQpu`3D}{r{9}E1mkJ0TnzwbFzVD90_H}J0a~3J+u5^S!*RJJuJmy;J?~qzvfU>z z4ZiKsU}*{cY{_K;Zca*NTcoCkPc;x_7n6$B*SCcTrRk|FYX_gQC;W7>2W08wS;D;s0giIsO4`JvfTaU+XW zRjS*v7%Nc&jF7NrF?rZtzVDNZbB4ufF5Pa6R6hEE)MCPpaN%jHW}G#F0Dh zGWF!@XL{^CG~#{+0%?npPL<9&1$}082#O_SXC|R z>bEMT&UMG(5Phc)8~g?*osjm0FD^CL?=)ZJ9oFw*!e+sqDG3SEvJ&a=7SoaBpkNCo z;f0Jh$s}LS_WS0$fs#c0#1y{#-QC^f@~Kas-t492s}=&mpH0$^@7C^IR>K4nHhJJI z{2}S#W{EG9GFeT4GU}MGqyTVFys#>{A z(!VFa_YGup_e%RoD5 z?om7>Lh$OV-Ts&P*555KCaHK1!cSPncwKf^QzF^E_N@u0e|>v7H8nNzp{rYxK+t%&v`;#D6+(p7O8iR?BYl0d4%k(rAh20&l7i~v_zSW+E9Q9#1C3Ek6Z zGDD%KQY+xk4t!E1MbrHrZ>*8a{&c;; zTCY?bgS}w=f%wzmrJAPVy*|d~G$>H*<&Mj>aDn?o%Fo|e*cV+1h~OMKeHL(WPv$f{ zp`+Qaf7JHHARzd$%_QozE6qlwHj{F2oauSp56wjwq2~}8gQlU$vF>Y(JqMRTY^m2{ z3Yxn=NDAcJHtm*LUEQK%=mBHodoM392iE1ZPZ&b{zD$oY@MWqa%nIK8_Pj=TK`D_z{}rEuU%HmAcn>JR94?n7By{a1{p9`fTEtR&&hL1G zYlt?ERy_1;7`fduTwIrpK`XamxaQm4{ch1DLGN%o_&`)|((k8FNNQja&+xuOMj_a> zrZ_h3+E~+V;^rf4{M!pg)G#E)KDA;Lh-{cG=-fu15yO$puEqb0m z1a_=I{usmw+|)tE5oQDDqS-4tpo@INZ(bkBUcY4ih60+U0n25s(H*c~JX>>h1B1xZ zBgbD3hK7bf5XaTkv9##@dCGjnYs$>|^r{@O*UxtaZGEsfu)Q`9mPAAPv^gX0MsdE` z=0;>cudm0ilXKU)2C+c8ZvabqnQ3M?A@^0>{rX}c`SWcfu%R9H>D>lb(FzE>q~%Ry zUL5%b+hXxP^^IwpKr?pSt}kqh2~(Yr`ezJl7#Ld#S%$d9__1RoHHKNu^`s>2Q3wb< z?8+;;B8bs2Fl^>3dZL-z!Z4i!fb0-poNjbKw|zwE^=~bJoRSg<1>WzN2)dtEPMY3j zh=$xRPd4jn=@JtVyz`3n_7yHUD9 zx{>bgyc^H`{+ux!lOvVV3 zZHDXdN>5Pr3Ovq@KK&(mT27k>+Al8Hb=vs_IwQOP+_j>2>@OH15u`uA}v)?iC@OT83sTSSJ z__(5$Rx5~U(`t6SzPkF;D+m^uFx9Bx=S20k=Z*!dc99IeobmR%GwC!Hv(};9(1fA- zW_AnwLthfF8=w0C6bNEJ)-S89Z;SSrYJAw!y@*gcI>b-dPvBqP?hZ}RFtl7=El`k@ zu-aPx8sEs%3KG!JXB*LMbKgDrOa5M^q{Z!eB$es_1*D=<_E&rxoYr~lF2}Qr--{J^ zlEjoxpUlh6pLhV#FR|v0PRGlgdqH7tV7r0VZi5o90T^_;7X>9HDzeMfQSQHvwEb6= zZvpjYS69yPY&N3DMq1+!sp&74#e0+>4j9ZO%j+-upnMdlF}QhmV$t%8=tG|Q0vM3~ z7kN3)z=l?}_g2|H2+?*xE$d7!G|*X7255w8}_h-iB{xm5kiEd`%!Bgu)4Y zjWrSaEqm<9#5EhL?b1qj3Q2(PXg&`5-cQ|(?RRgf!TR|Za`L=|>VXC6>yWP?hNVsx z5Xk^|@$1uSL^cp;DOuOpOf+tV5neDRM0BQUyz%{sh5)7Bb>f%JgBy6Sh5WD2Z$Ldb z=OrJ~WDTT(gGmkVRCx3}Jh4D|&)5DF)#(GkIGufJ_40PN<(GzUk+#^~;s1j@q3;RD zZ^qg6S0OrHorHG;N&3g7J9P-XAb|Xx+1?Q)q{jXN;9u6T1>1eTMl)gKkb;uT+Zuls z81F0oprahgz(FL!f_z4}SHF|+prOeS&n+)0VK~}P2q1}Q0CWr>k&aYBK8aTkxJF?x z5Mp+{TVIO*kJ;}<%deKuAsr&XvxoeQk1hde6aRn-7igV za)a*L3;qtq9^kKpa{j?{BY;?iA}L`ru%CT_%z{4{BE3%2ejodu%@hlo3}!ylwKd`e zgm`%Ov%0E!m(^vd={v~S!59te7ft!OJ2Hae`_dx+hAY@U>C!q5TSA0bg&8fa*<^yj zB=UR#p2$K?!qpj6e+x+<)x6&|3sh(A_J?>t-1+|fQcZ0mquL}{^n5$Rt7q5nY=mur z5ZMADxNhkBO|DW>YAP>?n|%q9#;g27h=U`*%~3RAiWvG`R9I1K>1Ep1(E_!{wdf5d z1^(F65(L?yxoFr#>Hm%jSL^zbHdaEc+q8BfuTO0;mI(;}GGx(Tz_LS(gnmDCLj#q3 zaBh_0HO;la=#%T?0z#p`;1VsWA}tQQm%ace>sS zcB$zyHEDi)C{Pb=p@SO<1BM=?NEL*>;OM&ljvfH6nQ9WipN(W6Nzs@{7ZWr0U%RG# zr6v~aRuLgJlFd@)_Jjx{w^x3ZFVxb!m`O&@>B z6ZL~d1rC^w!^yR$r|_sGAfngJ2z2_0*l$23n#$+aR9zj54NUPNv`BUi4!$%yrj392 zq@&|?IRAP5;27D>@i_Cnz$8TS$ncK(!kRb(7VQR8<(jR3#+P64F*xj# zk+)$+PUv0fuOR$!EOU0PopJr+P{inTsQv+B5Uf6-xn7r3GqkkRtlGa2UIB~>a3E4W zwn+8w?^m8#jWYV-ju+~6%4c+1T?5jIKUg!dz7M5*C7h{LnBxlK?vj&%xCby<HEPOXhDb?CppYmQPf^J~-fT!& zh>3NtRk0*9vdw%}QV? z$nECj?@P~JEkH#jk*VN*+HKSGBUVG<^Jjpvh&&~v59Cxu^50qi=9RT{-5iLU8MYa| z3PXx?f4Vi|Yi(tHEut^d2}*z}mTFTo(+1Uy+M2~ShgjxY<6mc+?{k%CZY|4PR#I;Q zlT|e|noZUz8CqOH5f3`)41TeR%S(s$o9=RzGEIlAArtWV3U+iP>7JZ?j{XWpv0Knb zOPynu@BF2MkopF}qVjclT?bODvg~)x&uSU6yTFkB<+yC6B&AVn$iAxzx|En0B`qyk z*97Kw3mi4IwQ=$B>e#qM1niIcY@p|iL8(ipiI+?lAR_vEz&buZtq#6t0?hpiZdxyM zclWtJ-+)IcJUsmP__#q5efibpr7b3?f#0hz0X0zZlsac*vd!)vv9dY9;9;w@+h(wg z+u5O}jRGfz#`HA{ox56I#EF#J1i)$^HU{ni&p2h_PTK zpPe~ndI?A~z;^jkCR3rIp@fd>ofs+FSdDgheT(P>S@g{&AN11APtGq(_%SKiA%qLJ zLnS3TPiqN-@$~uX>AW6#{bvs?MR@C>+!^w-oTDrmDPt|GM@!Aa!^2?w;|<}h)BPGD z(hGHj+ZCLEbs%bxY|a53_07@CZEXAP_39!#1yDyW*#|$_jvk9xV zVly%j4c?jRWsf{Rvn|{J=-$A87spwIsec&>~(Z4Wth)7fWkZf+9d;@V!1mq~c~0H{r>HcF+xJ<)Zrv^*jxZx@=7 zPv@-^HE8abr@E@{gK|mFY<45)wg?E?jRAV4O6BVHs)S zifAIMzqFhU6bombOvnrTJ(4Pz7-bLmjb+oMmU`;7D*1bg&m71@4KA8g1#1h`zipp4iu*$VFv)c!(xqRMR!p-HYP8tp+0 z9JC-Ho}jOi1kldFml}=g#OsumiI-?h{O>|mNhH~#{USm_u9;DiaiHw;664Z{lEDPi z4Jyf3gd(1Tf`S}Wi_cK^LzpikCMFUg?Fa~nms9Expm>*yf{N;#fXa=eWIYS$8Qvm4 z2EZT^d}j}^2dpHd3$ITQ!Xm9-VI$4@v=Bl<*u1Px571InO7i;IA~Fg>%kU7sAC*tv6o9-xU@a-cR10G4U=U}ZlSf61_<9Vz{b8SQQ=NM7tym^xtUvNY#o6Hyr$Vs?~pgjS%hS^2iWpjmo`UQRvbyXzoacM4Ths z0%NYIFWEml=`;{3j{#Y~7xp z6ZvTJD)O>nxED=HNqDdQiCU81_<)IcNVig?yczT->wgHDWgo#s zaxE3gA2-Rn;6`32APdpNOUP4{MZUa@aWWLV`CU(#8H&a_Z_-4YnT$(?SsE7cU1~s4 z7HO$)6l*+GW}}7a37t)lMlrbm{Qn&m{pGNUIhwoRmi_Y! zh>zlk6MGkBKV1;a+^WLKs{eHhHm^cCs#yp&RW{C)le3ZrtX`s=qxg4Bi(n(KFbYq9B9bO|;0 zVoc}CG9n`9Q2!3d^m0IJUo1GRN*dS4p|A3s(71tbc=_}&Fyc;kiz+>{7j##_wN;H~ z`~BTU>%?zl`G`(Lk0HG{?a;F5Fjg?LtBi@cN8@Qp@qzn;C`vNJSARu9w#jO8-bGsh zr#FC@!>e~5xb{{vIV0F;dIF0K*4TLEzk5CMaaXTIpqC$>y;ki}U{uML?93<4^mAz|+?)G}-+^*tW ze-KVZN0uGm@KRTDT{D96~qN5x+&V>X)S_0R#FgN96 z{M2tuwSa(pi16QK!o6aH`0K;M?_p~m2FZ}g5F<8>zD66}DAc;)rO2P)<+32jD#Nhg*lF|U46l#o+REIqWXz%(CY$6)Lx@>(F_++TJyxVLLs~Xak0N(wIDs=F8P?@7Lj_ z6X-mz4`&WyrJuZ>R-Q8(3cOGKTNV!v4v;8^&_mv78!VGvGGf3JwXAkZ;joKP#4zy+ zK}(fS{Q0TpJMe(wvh|7kUW^`8+^`RXf~48#XovjPFKg#-ghhWeZze&yPo~PWIEYcp z7RJU~lzV&lNn_*!j80m&1Np>tr46$=W{tAz)U=u%2w(QOI20rlopv4YgUY{CoSD?l z&ox2$kn;08S{wT_UvI4br1{&gs^fLM>+$_)(c`3H3!d?h>2NX@et2GXb_%=|pqHtu z59mCcS@`LKS>)K%(*5O(fSin+I-~X1=aH29BX*A3A%=b-#bOl(3uAX+0M_rkfE$sO z1#?kfd7AW1PFILOoD-afjM*ecrA)p}wQ0J|UK%;!bf_vJR5cPHXK)1JJGCo+Xw_Na zZScvAwdf5;u=vFX4=9AbUuuleA3e@CLPEcBSj@9AF|E2LMZth|fJu-#zEC;h+=_y- z>v*M}oRgD>pTQBhHi1-}4O0hhr5X(mt1or-l?v4EXE{$ByNDaN{=&bG(lkP)5e$)7 zXUbOE+>SE~tuw#QL;&zOz+PN*>tbL^mKEBRgfYTw|&nKI2r zTazD3YM(TmwhqKvm%m2f8|v$2DSe6=)oB=jK?k~`lV*X(Tg+(58mrN(A3rw!Mvs$t z@h*(-PL=^GvQ?YS#=3l)sW}UtVAbfwMeJysVQO~Tw4}a%S}QGvbUvjxVOx!{?&;Bz zMq#t(Sr2-E(%Xc=2;$}I;SiGdv?_=&zmGjXh@=QEh#~%aYuQvXH#=JN5BKM3 zIqqEq)LqFX-|p)GeAV*ucYs(D-tHx`?24z8>vb8u=B%@$OA7_(0s@}D@20K=crBZKV`HxzHjD4>UN2&g$z`5i_3Q@;++OVG8OB~x z-pj}fJU$TM6z}BKB8Z{=5gcW`97?e`E2qQ zd4Dj0PR&?HT37e!Z1Wpc8_(tTHUIFCBmiRO?>^fmr*M?zzb1TMTUg72`5cE8MuS>q z-+flKybM`2HL5;O%*UdYeSfpg2naiqc55ggZ#oZ&5w3Wh1iz_P7EU4iTUSt0V(%|=)Ncn5 zZ=+G4tduqe<2|FpH@mcS{}hx_Jh{iI%_Bn)xog2YQm<6^!zsDa)V zvsC4N^{+m|dB6NJZ1G~gP0oGtJW2O5F1Mq0S&ICX!baTA}?>I4^r|?LG`#YTI7R8G@3O9{`R`yTgO~U-w+N1Id}c41Dh=B zG4C_BCa2hA{O(Df&oc@HbCsA`xW(runvel_(dJg3d~OdwJ&k6=?toBLljNc{`&;gM z8C54MM@Mldc@q5*d!cQ$PoIh=j2Kw#bZy4iEZ_qiAuU)OaMp{cj0oE%7dQon2{IDh zHP4mF&;>9MOnw_C{mqQls6U<%b#>i?sy+e~wH$t`UHJ*HuFx_w|GFcrDq!-mHckxn zNKZ|C7+iTwrIeZez;znw1rk0uqckZirNyQa_g&Rz6jWD4F{KBv^YU|JYN?1y#*GUs z*z7KgzHI~#FBrFY^iCob?eAj>;3Ki3I5D_*1!>X0L1=$Gs`;2}X?9GDyl>@ce!P=qMhsBK=NoyiJTuxLl*3w7f(*=1zdRFZ>Ka7j4~@81 z4=kuz>F9u4p4je8h&Mcx6z=D6s(#~RY>Y#S0w8QMDBH1AUdmn{TqZvNecIS zs`4+>7A7X4;o)!RxS5!`hTkqpc@;+K*|BK$&_zfIN{G>1A1v3A3It8&|N6Rfv|DQ_ z^2?XkRiTx`g8X>5Vpt%ZyWQ!!?)ie`sVckrey!WA)PhI`PT{j!+c!Iq9#^WO@wqW# z1X_xJdU9Hgk(KNAfjd%i_AewRC??Vxw`P^EA<3JD+9T zgKR9*c0XdqQpm>7f3z;&zG0{$0O)iqceWzxJa0b2XlVj{Y!;vJ`mKo;Fvle&l23rl z%g--71x(YgV-s6o=S2^FC!LTOW28u){o^Bp?8jHDANIH~yzL{D(V}sVR+rw$+{BOD z1@Bq^4hanO3w+sQ`Z|_{BmzAQK@SRt7{>bACzjM$sna0CM3^BKY?3TnH+px{$u~hH zqv`F|0VSKud<*^IF`TJMNw?>28S2}b*a))dzm$J_-v+vU4DhAfn7!$8BXPIX8mue* z%sj66@AXPRIamP(>?JxDR>x$llG7y&E7a` zYol-y5#_p94m4<&KbJqRv|lR6dvNfGRk2fa9Xc_r7ZjUNs+mViidy{KO-w9kx)WzO zNPELkPY#Hr8tSr7^SX#8e z*5^AD1CL5tS@qfYU6gb*m7@|;w6q=*x5lt=_NJ1P^V8Cn78C19F+z;AAEItS-SB#w z{1;w4a1F6YL!HOla<+~%I}Mgp9*r8&g+w~z?d^s1=A^U|6zA!X6Cr;y|LUcu6n!;~ zlFYmv7y)rVL<-9Wq3a`5jwMC7oz!Y`ZYiRFe#+Q>|97KNA~M7Mxie`{)pG3Nb8-CR zLB7?P)L?Zy2e8P9`zR?@U*}*xTcJW57vt-`Kdc{$lkjIKe)gzkj;}P2gCmW+eqbL;Ogn_J+x%_jTtAMr7YRT(2g zL&58IuzQ#-ROKKYCrXxQ(LeAp|Ik)t<`*=`_?YMB;+lFW2`{M^rFE$kGi#u~n_^tH ztrVLsP~O|x;%M^LtsJdO9IY{v62t)!!})B?!o;29s5fTYeJ}B2_KCKPVtyE3%-4rmv!KT|23yOa2hb3aZN)iICCV1NU(URZP!}U`D-2TBhLMJZ-7M0kJ zm0&NWpZ96|`Nj(OlfUiu;R34hS}0??+hv^J^Xc;UWOTmtG=I53k>_>3?<55k5ffyFk{&?A|0Tdq4_fC8EcO;&?#Z%mu-9ra0qim=BMmp6{sw<_1*#*t1 ztwl4kp}9(Fj`L5sVBqnm@DnYT)R$Z(;J4b-AS5AieJzl_)M_?ZNq*ng|EEqPNHzBH zr5^S1;E`;e2!JfTm5a$~6nMHQ7J+rNDp8l0KVI};`oMNj@^C*Dsl(Ou-2Ra7bq~JB z_F8!4x?i5#F;fn+Q?Z{u8T1#*nD!S=;JCWpo8%Qr!8%QB!tO!NlO1t{p%i+4vD+Ba zZrbQbw3?NSN#jVm8vOOxTtvIQOor-ggE6%{E=HVD25SvDue|H?*xb`g^_dpS>9w|& zmfg)sdTc(!*kz)=#P#!0y+C%F^R^uOI@k1DaPf1em}R{wUuZLhx^H~?lty_C$^*?% z*3ltIFc|z7Q-&ThSxF*M`NhNuw$llSNy&rwf?rnLVDFrBFbITk7b{q=trcvACEI04!bWu!8rc%(575v6wV_9{JFF=6TB#X>eK$sawCR;c3; z;yxZ$*cBLwl4W|VfFew(W5n{iG4ihROmmO#<4Eo9-sa$7on_%e%JXStO?81x%IiS` zrTsT#44{@Z4e!Z29jT*c=czBx4nKuU*#0w_LHE958O)}bSkHOMWazM?OPr=F3)Q$h z(hia2yQuPa*z~!PGm`SiHTgPuMulz;%-sW0NBt-6Z9R!ZzQ{v=4YwRdKn=TM-Kq=< z0JjI?tC*>&p?rN%{)S=Jf8vJ|=~wnDDs{uDBO_4_{kRai2)oMbVM2KdrpoCqWxFP@ zEaT#Qb`2;ZTNR6uBX2kEw}za*7AEJ!2pq6Fpga6nc6n7J$66RHh5fy&2Cefw14odn zc(DVi$dWwT-#iaP!b43XE!n(T&%BhYq>9DLF?=J9oEZ~YpX~`t34~FHCv%j5^f;F} zZeGp&2_B8;WT9|fXW!Q`l5~pUzxjE(?vax?|8T7~V-Mh-z_jc4w;wxmoP2(b9@&{i zB#Op^K#PL-#a~$CKOFn*>rtqtEIkh~v4F>ih=>RRPD?QMUu943|64F?AP;llPEO0A z!pgkiidX8YiATi8|63v=m?@{Z`1;Q#fy`G$SsCiAtlq^pV^140#-Mnqg(rlV8zvALnCq+}z$K^+prces7)r$%;C#EBz zi4lRenzZY3F?zZp9AbgsXt>QgIs1uGsWPvRNd$>M&+sNWDFYw>rKS|@>&W-sVzG+y zsH+^h_~ASpHiN?b_N@^08}-qo2LyF9*YnW2= zz`QXPNSRVRu%&aq7f@G?@`|@f^iqMy2ICLRZRj*Uqr}DAlBXlQhx84G5YGPcu|sE{ z6{uIsLLwlL!&5NT{~HeA-@JpZDb$QM2BX2lLyM)QyoJ1Id&Q&B?Lux5j@(XzV0tKc3DCH*Dl6C?EU%&RY7G$3;50(`otU;c9YmiZB zx2UO|pM>$&AEpSaf3b^(EoyKT&7v>0eHKI_l!r$W9`R>80otg2h$ph@fX8kduozU>(Gt z`os_ONkVk>oL6y_{{R= zdW9B9WBVHx$AmKl3&FftrM9+KRz`+StI7QN3HrGGnYdM1y~%n%z7&vqQAzkg%M0Xo zpnhjAC(HTVF!c^Y%G_KAki6pKv4Lz(UA;(27N{76C@`XP^16WnL0TI8Cn&EwZzYno zySp1Cptd<3YpbeKfz&yPh^MFP_8DP)A8)|{2ipc|iujOkA5F~Z@YGaD4Ypt@(vV+9 zO^T71`wsk%zCx^A6w_vFv7gwA3JXKv{j__%AuuVg)TlAuXJ_Rg=lD;Qi%RJmgxht`KaE9Ijye`ri`4beiDp=+i9((!SlF8iAILmG%5(xXk}o{kA-A++m4h%7d=3nR_dU9Vzk zzZoUaYt?R}&}h_+qz4b8!}&0~Q$$>%EiipM6X@XqobLN711fol<*%G^b+-^8(KeI3 zDxD#qq}px>P}b35XG(m*Pf4WX?GV-PUX0|L|fsDBqj|_ zVU3=K#(U28*4E)FYY~yoy(u$EBcM&zi2x$tO%FjO;U3F8J+eiO z%ZPtapg1+#zggJV4m-dZA>af`s3n`R8eDyj@vwy`&8O2|5=};ZuH#zwA_SR=*PVkG z4bu}ND)oZzM;Wd*q5S-yy>2>>!QzvYl2UKK`v-*RL<&5iDaHZ@6ZbF$A1)fi@4YfV zevFYTE|$sape5vWB#0AyE8lDpRq@fxOrpfaia-C|K0yd{rk39U922i_mJZA-0bLLa z3(KGw?^&eD#lV1qk1x&bqfRDBnqSmuEiaE$=^q~6OyAnr_@a%G(g>v9up}+=hP>?T z-BmAI*!&@a`=MlxDF!<+Tys9N1%>I)gW-%{g<%}8{IR=)MqHbM*0bDl@X#*Z^`d^5xjUR z?|Bw4oLNv>>foi7CU@P9qr=9|j*X2?NkNgydz-zPTdZ0RbZJCfwg))vH{TQ$Pm@@U z0s{kI?#4)B{T0{b=&w%Z4ZI$%$*-ruJFq9v#Md^G2hngy!F6UtFK+=v2ao4N-`h(W zsANjI+n;`V8T4?kpenxrOTl61U}f5O$iwfPfbiE7Q105E?#u@1VZojb_yozq%d>rN znVDUTjXNg(F_K56q=pHJh^Al20_dX;ANt|zJB+5gS>1$5m*)5LKNhEJIyKfViMh?X455HM<-BbD8;SAQ*v z2I9U-Ra~0BJF0g&M@Z74BLv_Ilb-o_pl}&VxDR8cVY8f$9MQv^-eN54X}P@bYpyz3 zeMI*r8n)6sM?h_&plBM23#_xyf;%>z_Uw7Ujs34b5NA*YI+Hwhuujru%8A2P2BCZc+C6&rsXLgeI+qSnLegzavn*1u zi|(Uq!7Y1D@DGJx0I|F4>*O0h@kakD3c~Kh1`fU&ezyj!4d4wBP{=4LwMpMZL`Jee zh=QO8{-8DSYP*pNO6R?#&2Q1xJ?q2knF3#lz1vT3gV#PoqNjc7C=H*T%F*~A7Jw*+ zIuxDIxieits$b(0s7VN3o!>Eui4Ayux{DgR-TDY9=$L3gMP&V&2yP8CX7?vxum~n% zoL$XTZ^20MjmjSn-Cb1aOuy<7aOS2A*T(*u>Xs|1XdWNVde?+@Y@I<~mX(>oXvF&d zha)miG1rBVfX=^V3eHy)(}U2>BIEX*AYkLJ`bPitNld)S$x*IVXXh&gLq4GmCe+^< z1(0VJx zxz2#k?PT`*0cqADOC`I$7z%>-*Up`omxm+_(RBnFKT(!T&xc;SAZNGmh0ZBqcAOxq zgqv;2-!J4iI3uLjj~6wD&d!466D)6`d2t{zp@{H%#Dj1l$owQDJx~rcPy)>rIQG}~ zWrDfi<{uh{FPFkXoDh_ivh5!x|LQ0e362hW2j#Dd&y9wAXe8Q{^{*T2;6!`bki3oj z!#z-NE(r~n=iVo1#*Ge4cnd-qQjT- z?Vn#4;aO?GIhc}^mybUpIk zS*7VyyA1NiG}_8|X*6!|My>Xtd4qt zvq7NOR@JC(S$YOeXO(a~`_RyhA>r292-Aos>< z8M#H(cHs2k1J%&g5JP7cv}sl=xUp!CH5S|vQPS{4l_>Z^FAw+z;^ohJj}BqpA85Vh zb&?yKuzaP=C%`ysf3<&9RX2)$@PILEfCkZmYj{3nF_*hiff!n+@jIgdAsFS?#h7_; zu75i6zl~!R$?Jg{*ZV{~Q=w>zR$g^n&Ma~DEk;Oowtk-9{A;w4iaD-EP>cb!S(uZ5 zkhdZ5)tfS{ZI))GYpn)KVqjrUU)|CHK(s;0TqVC>9nN8}CY*YD`U!Me@zF^%v4cP- ziA(&|qDhc87XKozG&m%bUZaYQoct4IZ1|m~s-~uZ&Sa*H)E5eIB3un|rv?CIL(G@Hvg!GrWC+5bv74Uv$&mYmh4vB@Brg1?a~FwhXZhR;uaKvk*Z`uOP)=yF@{uiR=rDk@frl6`9d|L5ao`>j*h z^J!%kD7wnkTLam{_8B%6#ck}xooAU8< z0jJ~foHS--rOj?qQrKuz#uAV^7nipIBh$9}Wly8ss&9)Azkg>rEkEu?XZIRECD)qe zvLt2K@>PubipcRb4L(kR$URdFi_9ilJ3G9L z==X0L8(kQ%C8cFU!$WFKXU&hz-SOnUD12#fxOa5r16mDwzNI`ud<O?j3U;^pA^tkP)~Jzqz?j$Fl?jYIduZTTCiO?s$8kGq7B) z3fGR8?7F?Z4I`lYq5$+zD%-`l^pS~)i9pY4>1yF}8|aQs1^?9D`QFz${=z%!@P0!G@roo#CjCe1;@o&N@Y28tI!&FQ?*%0GQ{%XS zqHt(v9nw4`G`154ou=8TDLeuk3FvGP00K{K{?${MhnxHC-s>qp39o)Fq7g1HU)~Jp zsEx_US;@&+i}Ra9Ps7>G24P>nX3%cvNc7#Af$`+g5l9a}N?Wy9Zh2AK zNaHZh*7b$mn{d{sAC9elHJ3p$l5Xu5@(2(U12khDuk$#eaw;`Cv!?)SU__FKsdtD0wnfiL=zM2PpxLBo>1NS1s{o$>HoubWY z-60SE{RO7sQG+>bL*sWB8dMM@jlY+YjE^_b5HrDKW>Wb?&CIQqJJRw!Ixx#6&S(T7 ze?(eV{&=7DS{tHON6B`eudgp|FafvR#_jplz3Mq6Hxi3o-EXrnJKk#z#8hI;B&O~v zAt70;LpHve;sG@y#+v}OT9|vHuC+jau>5oozVIUIUh%`g_PN?q(Pa=A7ybU_ z;{yu4vMj($S*SM}oIZS)oBP^N*V@|KP(|5XQs$$2ttoP8ItYV1>o!gW%}q83(go_! zQT!U{gsO?&H<#%>j%YQ{#FvMLgjkqa={ zQ}eKPcG=I`I`g?Y=hK*we)yCw7=V7{Ml9913^sj71_QV&M18p}g<2cd!%(2}H_6Kn z8sb7gA>pEomvlUwCyyO4t^{LAph46>oOiHoYym-|TR+0C&}&T}?*$!aVSiWK+#Jds<+?hY(IN(Qw3YcO+^h}9Xe$;!qL&o|od!UFqS25VIe1DRk%1H;XE`y6S;ev-Clh2F_Q%Os5vo^awxw%)VBq(xi!d;Dn&`-D zpGY=2T9UBJXmz_D2cBf#iFlmi%HMmPtorCzce2zR&Xj2e`0(wI9@GoT=eTIL2<#(1W;V`Jnc%}~433YnE?gUG$F`AO}4xgFU2%^>C zA5uC7n#@y?wCTG8JoZEsxQo1zp#gjXlH4WJB~xzfab|z4iW;*57yF9RLKky(ikx0; zm$;^6>}-AXTK{Dmm)l!_Z7lx%UDS&`jtdOtvrO(5=FepEClCXK@srrHjJF0p7Z*qa zm=7I`s1sRnLOnM(E{?!tv8PLP!Z=5^Z(!ihuEV2;$3=Qp_Pf@>;O!;TO9kpThzJM; zx)_BQW0~X^(KQbHSHKBmd@Ku^l8Er^?0g7%w95xNsHaC9OcWV)nAzBz4`$y_`n-FG z2y%9IA;jqO>!FESO-im3ADYLN2(-k$wE3#wWyvv>Dw%4Fv46w-nyjOs0DOKnKPA~$ z#@;0j{3KFURE++SD03f;Qm0H&stp=_@WkfX%Ch3#t4_>nR2kqQFLhB&h^bggq0D#N z6aIwfMnXYCDf&$73g~DGY5>SnFDAmn%Y!}xXbvcM3O1J8+PeI^atBomwl~K9K96Sy zef;*O_WNrQIm_jfKDbgjv2ix!OwcA$Qc#X#5jD+=!oDi2oea#$NhqzQqG@(^H8r=* z8FkGQCDv+i?e*Q%z+grEtna5DzB^kMCe1*zl2Gq%r{oyo>Tayg{x+sB-oh=^wb;Hh zv;VKQn2eIjZgRoRWEOifX7%@;*WAcWYBR1lszg}dDcpFU3pgkQN&qa5`%z8vXjodvo>*7jT290Ku4|KoL_u|@*ZuAeo48)Rzv-lQmdS_ zg}yJ!{%z+vg1fmwgYL}9_UM-dJV@i<^~Ms|(0jz`U&_{BEz$%2Mx|iB0_bSR12oMC zh+t~Tyc%9JOACws!9nsLyJ;2A;&nChlG{qbC7#bZ?Pa}*Y@G5QKcC82FU{x44jmC`c` zcs(t)KRjjh87t&!u1md%DR?}Xi0n&IR(Ul>&#^>}E6C4c1Sn&u61GkpnZIqaN;79|b@ni^ut;D)0iz ziIJlEL+GY4kN!U_;B1{kjGp~*XL*ty_#-a0xcK24YOy3S&c}noW8(JQ$fVg=!&vih zzV-TVc2I`r89GhrQuDQ~w77)CL~+f=kB?$xPe-lIlSvyf#_eOpx3`D|N~Z9K5f@=d zWlG6X2$8P4T_NQrvAZ#Wmt)*dw^VF3eHuxKk#lt(+mCKe0(U3S_(Lh27L~h7x1k1z za=@;`r&Xra@lBT z#^1PNoZ+XCWVogtvH6P#kN9RM8PO&52kaaXEDVKo$7_pKgNE^%VCb41_Uq!~jg)!x<#q*4RjkHhcgc?*j^w@Mg3xK_ z#1iRilL%MlSo0aRS}K5@hkBynpYAZTnX;Iv+@>;}W)5E7y;Xzd5&~l+Q85YR<^+b+ zRDP|X4-R`2t%!XPwhoFsyIDl_-eJqaTbhE(bVMZS{4Qrx2|6+3b!N}fn0DJ&^i6Ws z+ta0kIHMCje#1-!u4XZ>mYW-VABD1r-?q%DYH*VV zK)q-s?=EZg9Tcn<*k;BB`92b`*k_p+_NE`dEeSW##>U4#t)s30V|k;T)qWz@JQD1U zv8f+`xZ!oVX@fD4<4r&KDYoy7lY`CC!C|y8s-S*-ZO!ZEl*d#Ah)#!hcg*wa^Gym^ zdb)B%8-UtKK?`o?3SUQlYib-hCO^Pa63i+20dHB#c}2PRl(=BF(6q z`sLPI3fKNnK1jhmD&>Fl^fIHr)vM}Z6L34d`xOz`yzvDS^ft0}LQRIY5la0neO^X1>h$UAl7Pgv@g8;>N<4z@X*&Gu=9 z)M7F=x9Q7UK{XIGR<;vJ*GVagO#HJR&l?%Qh;+_1L{x5*bBQmuzJ`UCApl;2mvyo& z{~k_*gs-{ZagOVuO{~l{$pM>^sDt>0N(PWSNH}8%U!*i|pi6YHuZd+O|NHqX2M&iZ z+eE$PQqI0yB#8joOnh?BHuA#8E0s_x!cAvmNBhKq`Aa1e6{mgi}7AGOG2I?~#FYg7IT`PQQ zyal>*;GDV#d)@CBrJ9yL?SAviZAmL_<6GbQ7tas@cJ?U+9f^o_-Am|DGja=qTJHXV zog07WOof}(C%(NP(5lf+DVv%mcM`A9v-0y#FHCqmFSll`Z7cbuz9~eobp%S}eyQpl z?N-@(wxN&A<5P1&5pjgrX}aN&;cDv3^YeEHYOJ*zXSty{jfE?OM~FuB^~a7Wt>Q%Q za>8-onwy*Z>gRhmr=}-mH*GftM=yO&;ma@``pCDFX<87S+?^x>vdF z)Z&hgsNYIYAujuO+rKfj$3LVHjO8~dL*%mok-~7`zguGKPY6O$+0O$tcmnva5;RE z@%*NS2RNmguww4(9$z?VKpf z-*vll2Rr!9nr;JYV6xAvoy(U`x5L(ZW?jjOcuM>S3gO^9@lxRmOJZl(!h%S4!Z{z# z@#LiPp!8;w)z!t-*R7$$@`SA^hc}|RilZMFn%)t)O4@D2Vq!W31mY$Ew<@g3c$B$KSB89j@^%lHRMGxx3%P%F)sXi)-%x~ zJ~YRp{q2vq_!&mL=3XC&h(;3;rvRp*A!M7+u&|)HI9apmMx8|)x8`$lX<3`RUwlN6 z^54>AjvX7JAY0rgm^v4$($&4?)&0+xtvlOv@`F)QdG#Pe?gw`aE9)fmjt}ZF#6j>& zgf!LZc5do(DFbten#TOX!cgtB>^k(#b!PR${^%19=FxW zE#sh&wr8^Cx~2uXRF_#snQByYaPrO7p+$sH)=(}SB?fWER7N#Frb=3aP$y?6IMYgl ziQf|*GrFNTzZG-B;+lFV1F{`8Jq90%~oHDs^&X^^sEE|9u9LG7SxT`n0iJQ62V1DfIaIzDdhK-SNxjD8+YReMqi+o?U z3tAkpp*ic;algM_4IC&+f4EO*ZRM-CUfi!6WGGQArt|!S5o$WWVVAU#XRHj3ozt*# zyA^Hn`T1Aa&F0(K3oT~!w+sBF-e%R2`2R{i(NDZmO)*@BK*aYrlpoKH+cPX1?e9KV zzC9R=UfmL^s+r1r5C7&3XuBwr3<4)`m*T3!TzN#mWle~*YK>op2 zW0C@n7*=QS#}sni#xS87f$(t1?6{otWYNRx9MdM|uN4_SVFHbeRpBFYc-Zg9_TF;F zQGW=PP-ouc-N&lLTk_h<_w;PNI$R<_Ij~v0Z}Dg7*a}hC;w1>c3jh+>``UjQCfooLs`=5$}WnE%>7dI zm4U-5_G1!x950;fC99S&V=?0s0H3o_U*PjY_r6zRN@9+!#NA-3R!`1fK1>7%<&vwasp||5|h(3ON8ZMTomrS%^$D89dndui$KF93qP+lD7Vd>Z~{{Sl4}}enDy1HTduQr?kXxDPL=Z zi^9G}CX3OUBZ(SIEaIIrTvb`!x}t68e=8a5Fk}Scj|;dT+(4t>#bVO%TmUeN4?6_X_O&ot$V-SI;A2WPH( zOs!0;%Akvl_bkPP?1?-P;pZM>4mr$X(;vXf==E!`KzWHXF4)@Iy0F7d9Sk~c>i1G{ zX7L<3O6G$OznKRpQ;XRQCUEiaz(4>%)3}bvR6l{}-J1(lUEo@a+Pz)WedI}I2nTn@ z6dIvcs~b$;cOAPxrs}_xK_~rGBqStL%>vR>PtcKRNxi&EN=zh%UhYs4sgM4aGAx_V zRu*gR%h*NYuCz8|c9d3eiV&UCAl4T`I_gAQnlP&c@)GP;i3j~1r#Z7ZYUOv00(YK5 zF_Uc@sLhL%X8s0a&lSFIlbV{E!|~Xv_e1BA<@m^)WpkjxFwxTm8od<(Y-w6W>1-A@ z++{-aReRav0joZeX4+aWWv%HGo{8p2DxdwvDMiuuCtpAB+clyBBzkrDAmPkJhad8` zadQhHv2IJ_2dqL588bW)KXPe6dkb2cxD$MCQF8c)xjpNgoE(Tjct1;c3xec zr4w1~nZEYPLF9(?#3ZV)p8<**YAwIUY^EV|Iqtqpu z`Y1PUaZ&_$*gV|-So`K)pdc4}Vs8u$CWlPPBzsdFlg`5O?5LP5YkEyh)YHaU6XYPy z+uI!*wKHapkwknN4L0w%#(*L4P{sFoI44bf?v<~qTB6neu;3ek9ABqCGF@1ooSbZW z43txz?*H)UgYVB!YK*2YxjEPCc->W;j?uL(7`Fk_T8^W!xwyEkt!&Luq*2M^_nSji z10}jEG!&X$O}pC^W~Zj}P!+}H@e7}$b{_p|I7eE(e`}aBlF9=z0w|S*LsLe$ICzq* zrD-Yn1a2Oyn0raz3#)9VE~!-8(?0I%zxr7liHed4{8!A--r#(M$_F~cxw$#BH#@cHczDfvzSQu- zfazqWp#g5XQ0Be8v=}5gNl8;Sce6}E!MYKTeEuJjJHnT)HMx?=w*88dIAf<;ZZB!P zx61gYbD?hp=qk)EaAPVA)FKGo*%+2jE;Ur_*KP=KlL?Xzu835S{b%!L-G!!Z$@lsS7&}%h*Jg)uultDLdQSYL$O~ zOU4_%N@ln29~h`p&uh*0>>oGOS_%e}>S*k0nBpKm4Lx<`vUtkNb(MO0v;LUeX&eij zo=c9zy&2UH*a>5G01#w5KMsR^RZ|;sBu-%Mhh6TC2R531A z$_3{~V}}eOEG2b;u7L>Tv(k(wm=6r%;aYUQnKBEfXsjrVmX5azrv)Qt3m6h4LmJxw zUd(t0zS-aqA9uLsPYU7OZwrW_C~4-SD{+pkiv7?>g4Q50aWRv1dmQQQpHk&FCW3tO zuVS3>a0p0(WiaF4rsQxVUa4HI1+(&j-&uo|eK%8jz^w_>(KLv9N0O-NezG_jX)-lGO&U zY)}2{hHJ!(%E0CWFjMT_fY$imc2!9Da=o6_Jiav(_HWQqPyYV8I0*rCNZi#;La!y} zxv1z>{VL#^u&c6fY+N_MrlZG9a_et!yO^6Qp0Q#7ZedZAUESK)XgaYuY`|C;_A`q# zcWMe3bq0QuRRt{m%hhi7lMX0I4{G8grWUUEcMr4T?I&_`-vUndzY123fF<2{54L{l zLIy&08q{Zt z7+A;kguer6ZMU8a&IoLBw!#5sC;b;bqO7c}+tBbE9><%2pJ!VmaK?s@vN+~HV z?G89-s{8Bf1^`OQbM%-p`7yXUDQSzEznF-Zct)n~c5`?Slz5z%1I6Sr6d1t|<&C4M ze9d6N`&|DyWX+F{F93#ZC~QU=tQIW#!O!@uC6nx~IE!2KaCaoPKiep6(!>y7vw1=m zXEv~Eq*0$=b{LH3sw^9|C?PLjUg*lp!jtx!iK=?ZdnIEB!9lnqqj1|yoa`oq)R$unc#c^hi10XG`6F;R%fseVs5-&T5OJuwMTpn5{%uh(mVmT zlc8TH#&v(My7m1@MH7T}2)Ngibn<8L&cT?`l>x+1G)E;J$DhnjC+QP*DNqeQx zyDM;Yc1}B=RWp;)#-bDH0@*hW&F&vxKY{z>)DFhZL~bPzB+?Cd-V-kyjmn&a+1Nzc zVHq4z9|5PU7CB!BqiQhzXx`iB)_*=2j39y~gIVi_VQ8}~#&Xf#m;(1+n z5ov;KM?md99u0QGQ#&>1lz{Ea$jT~mCOgv;kGpdq>1c}rS^#J~-MopUn=`Mg;-KaJ z@ff2v+jtWNGrBn+B18>fbDGwnCAif#-O)2Te} zftRi8qH-kMNYIM@QC-2_D1CcX1z1fh7#E61wi+cuwkc z`(~mFK4m+*eevYOajk_+nXpbuq{_)_u4kbDs+$A3h3m8hi-0w(rzLmv z==Z#idv^Yb*TeA9Th*h!9~{BtF>S_d++c&kKL)Gt*y2G*ji;@EmTG~02ix4Tj{T35 zydQaYp}RGXGwt<6MZ;Gk9}!p1VSjzj-M$Z^&hxp z2i|ps;g>k#vtp9&aFWuY;s$eq%iZO5na&G6>F?i9qt0}fc{D*V-Ql*}k(z=+Lykp1 z$Fhgv2v6q8p?QrOZ6>B;@&&St#;N*#O-i&F?L*rS9>pKg^kjc5k=oNq z7%HBjywIJdh*xOe31_Kh4FFs^Ir;f@7&;`@77rgqZvLEjGp8qB--6J{KA)^YC&0Er z68LFFO9Tr%b)ts}^#Nv}fMpSF3<9n10 zYy1Xzr`MKAtW?%t(Ek^+)LPH=1Jyf^Qk}?gxP2A9p--u+#iZ!YlOAIb@KT|>|8f;* z^>KW4wjSb};6GzXYpZrFK8}CZFp!=kFZ(c9&v*)3tprnNfN8 zBw;u9EDd8s`}IGB*?;c}SuUu5NOk_wloA&VSX&D~!HO-jr+2N##S&gY>{J0#TYB;2Iw>K(7o#nnnV z_43b`e4qN@%y{tPOjCZ#z%pCvV5L>YPbE9)#{%vHx|sPHz0;OuUn#&b&MzKteycaX z+s`2#MTpnQzcMMsCVI(`;9VKI^{HdilS8#Q&vJlu+ajn&fN^H82+40re%MF3>Sy{V zQ}2!MPT0i_TQGPiay!%Ci0n*)nUyDnZS@NTw)fnMYXFq~%t^z1HbpxEM~=A}Aq9`L(a3gYFz{v2fMWAZjtx>xA78af^?|%G6U7=8b<0BmL zdGK%e{h9+OM0~`(mmi9`VF^somfEiE5=HETW6U}t(T*ULaHC_vmk;cyps>+Bkw%Ir zDcMKCV+Zg^M<*w>(d9bJyDG!Mh8=K4fu&>o^T+rgQsjx+WrTx*;3r625#r~Bb3Jq| za1gjWRXrtun&#qzRylh33NJ9%FirlCg^QE{0$J0Q6RNDmoRvYz+z_`ex6iy`+#5gp zF<#1z*Nr7(3=}+=Depg3^Lvw0U?XAxxCNYz-=7U10RJZbAC5#eDhw=$O|7gh3(&dU z<)x&u?4g;NBs~IMJv~t4?d|P?>Q@q^KuB#jvHl)RoWlsc{?WWg0)|$`Kl122;0JQN z3H01#)L0Z^vVjTUtFCP0r{`n#V(-FC1Q-|_%4l0!>|G$L*Z(p)@91AUmabd)eW_in zMy}?eguEH6yH@|g6XEW(l7aJN#elc}dn|hQxm)vTe4XM0IxoW^-_ZqKj4{?;CHPcO zAOZCO>q(Hny}reMBN=cG($mqE78fTcCT8U0;NXB;$@y?WzvX*x1i}9hineuv%F2^G zM=j>AMH4$FpXJi|FaGuHp;nlJ^i*jeCphNtK3fJY*Xy^Wr1xAdmoUjvKc_@2>!?A2kAk z=+7Fs#$#1f6ZhM@yKRPqpMH0P!zaJS#{+-_2iV6$KhV_-f&8!1qPdUQ*u8w9w#m&8 zOK)^N+ibrdJbD7+KJYlO3kY~`jcC(XC<2XK3TI9ND@Qa} zsEn|P!cNem5jDx5_f;z~e?$d2I5_NmN6+h&x=}sIt~vDE77P8NqgL^Z+EwOdIUZra*Ulo6g(3qkoPb@Zx6tu9UVet ze`?JKLqkFeSs~sacINTXD;XDfTN*(Z1WLBrnwr@bP`iTPV*1_1g_DJ)I48&7P(2$e zaqAAkSb)A2P_FVe-?5G71?YM|V5vU0=78#KXD8+EK3}Lr)d;tnlCl8UrT+e1{r$l} z-!whRYXlz2Yh=8!u^&{ji4Wz=pY8blPIO1Y;arW4{q0(+(+!c}qJ8I&tlNs;_^!y# z3vTJfsJXEShgjAhJ7|VZ>I5k zD$*wq@q7IKT$=TrFL>whP)>22IcYymRVQ1uwD>bM^ z0!!Sv`FZd$9`{KCBHfz;vui0mOE(%`-IAjZ&!vBn1E^YGGmF z>FFuJ34xz5=27*>e7Yn~Dwo{5vDVJc&gp3B3;!9Tq!e?zK#(CD1RunvkcC&2G8XIo`^m}4Pw%DNq;{P^)(2?KiKq75 zKprz-l;q~-+S;C^Y*9c<6h6It;Y(5DYG-%)H{dKD6iJG@t{dMV8KbOiTH?VdCP#Dg`or=}82pM9p8o><1?C}T-e($bRg9vo6L+T7Y2#gXy6 zK8{{k(9*Eb)6+9B$Z2UwVG0nI2B(`7jIdHoWKN?{nO>{mcxNIXHGyR39(;KqhkJfr z`Vo>0&Sc3=2swB@_hPB!CG49`5}}9x76Y$~CcF5uk;fWyP&^@FV-PF|cS^n)n<2cR~J zV`FEPlTA`)=32g5x??F^x14tZ^mlL}&DQ5Q z@xm8`zr?q&^O^kH5_o!r<+3qg`26R}tQ(&Ad2VKZctYeKy|BOaITZhB+~&i1$>DKv z++r(skH~tao7IdpVwv@jo%tU+5}z)C1Nr|jwy0^Z9E616Va72d!1Ef4%|MC6$IlO5 z81daCrf&Y_WBPk8kPAyjc6NC%Pe5=GpTx$-23|Sf^4n&G8LZ1+1UywOD;BRy^Qu24`6CH1+(2lP2GDm#TL zqk^FiJVIf*YoYgL`(tT0l!Y>dnLkLbkEP0tlYFw?fdAv6PXj&?53_}5thZ-PdULl> z%(l-eh?hsddO1cA}z$(iu2hC0M|)91{~$wN#_kY>K8)%j@=Bk|u~roGJDOXrMrZ zW@qP@nlcem@RHU}N{6^^418k^Y7WR?tMO1#VYg(%l0H-`pLut2adAG=6rf(C;50Iv zJnGkhP5TLCuQj+|(KnhF6@!;dCEv^ad>fj|Qy+f4j>`G}S?%D^aYWQkQD%+Pix_+B zaB!TakqPy;ez_Svd@bx`KmLj`Xsqwid3*f2n?1lv{w~O7yI8?8A^&)x#>XPh4_A%q z?TL2bhHm_7OD=?Byt9^POv%8TNB9eu}vLH>K4J0r7hV-pD3ZMGS&$eA9jg?v_CML=> zw~;ku3Y7s>UYHLtw5w|!gwo2ZCVeE*hx-Mmm+n~(zJ0HfzcO7`xOm> zfxKs5g+8@uznG+)jlPkAYtIZ^O3?SxSl>FRLcvM<@usbar7B|6?bTk(hnec@j%_^} z!H=a>olgenTh-v++yt>I&kmA~ryV~EL{=f(xtRX|pceiG?vVLkEkVS)9>0$IQQlYl z$xm-W+)!zTn^yPJ7*aMZ8~)_6+Bzh!?bU}g%w6>Ng4RpV z?>8C*Wlrt#ZQpY{w({!!tw|OP8N4`fFQYOjmw&bV_bL+*?t}g{@!Fh8_$aX*}Dn8%aP}*&ssx;d9(qK$9Rp4b4gk z0)9#mp#yMe4_cBw|Gl}S2fu{n-G@hf1-&H6r#0#S?QAz1fh;lU*q!z zUisZh9j z5Qk@%&6$4Uvp!o4&-||aMH;n6;M#%QneKhCSYS{hy5Jx1f#LM!jt}hr6s=6~S8Lhs zzZF0Jj-WfcN0?1yR{49|DYHaiZpA3BY&XsQ&5Y<@e!pK`XPJjfRUPh6E?SvH8rN04 z*^9ley|G#gHa7CZ(D1$khy37{7jebf`UZK#5uDF!kxYfZ{D^S7>xqeKlrI774ZJeM zPl2ixs8kQ%UUfEmvOler|1sYCcVC*ur_L@&wn$gGF)fU&#RBK#a++szSBiOjm6$*Y zIYLORfR44OoM+`E5OL^lWvJ)N`)IC6Q^Ng0jaCaA!hg*$*;fZ0Gi2k44*}k~U*Hsv*Q6563@K zS&WI;$6q*z3^25af9t<`0nfv*MhQH4LqlN#)hHu}^EQX;D@Z2Up5bZB7QH4t^l-yF z)##`mbv;D8u-K}5{*P+uI+uExuCLtubvK=N)ew7)89wNz5H4H?TokyB#yb@=<_Blq zv~Xn}sb?M}o6Lw!Gu-`3JvyQS&+NNG4_oGO>w=jPR6l zICQ8vYs^r@)*0$)G}N42(X@_^ez&j7VBx@5t!RLM)p80bGuaM4l0fe5Jw0@ z>m-(ui4CfPaXM4CST!L2OHdWZ_g66CG;ub22_Ch-AA#0S@E5ZHi}mbEzTB_GHWV=_ z5pS6BW~0w#kY^eJXy3n~oZ(&X>j>RPzL-vDKzxUy@qkIU7N5i_I8=IqDYp=HTGY@Lqm=0q3JhOaJ+^uBs3kc;ZDcMhqRK%yvQ0 zXT^)7+^P7|c@XPL(Dpka;d!ZbEb7w*vA-KKzd=nu`H`;v1k)!gzl4PcR<&41Okk*| z>!9+M#3I6FN)|+@B@EkUmwH%-HV2$2uZ7CTj5rt2`&1wfGzST_N z_I&nwNM4RB*K9XBm;+`Lr5Gh{9-bjnZ_n>SLaROD$-8@diEzM1lpdA%oUOhU1JYk& zL5pvd=Lz{0@D|%>YyJH49G~ZMw>sX)FYRgJJ^h$zEl}Tra8^3HQC2esXJ=tyVJoX8 zpd-60{us^@X5Df(k?!o^P%vdSn4<1ESjALXIbU~VVqrnt3XJPuhuEMBoM0fhZg%_Q z8XdUWT}*xrRC)&o`YILzyqXa&IR`^z8T=SJlFOxW!qiC=EQ$?#jnn&;^<@%~TJKk{ zdkM7qDHeeS!#JEsUDS_fI;_=a`%LYxE9q@uA&rne^Secw;K*HzLA})06(y_%qUqhn zglqir z9%pBN>6HI?A?M&=p|4-qk@1|l;PHn*^+%*K&DCTi*Ym9NWx727FzRB#sy^EtE<#?rBZw@W(TvH9{VgABKADLJQ13tX&Dw@Lk9;38$H4D85VxQ7u-}F zL2sA<{f}yhz#LL>s|F|<1P2FUXy;cK(bPsR6g)gU{QO?iC4bUFZ^&)}_bgxY-B}EW z78nx_IA_0K$_e^`!x|(E8DzXkk~ohp8I8O_aHAEe3%Sq`JDb@gHZf@r5N7e{72+xJ z(|y5vNV+- zmm?60EuC9cS2qn*;yj_5a?+H9Q83!tMtlk@1bcD;@! zN36*(U>a<==KKdlu34qCRfgtLW;ArCooLJUZjjkVdsWXb4`mcEPC2m&5FT)cRC?YyYZhs*8aj$g?l3EcxejEw45IP_OF<;xTCxoukvV#LPO zSuIY_&T{gzOZf#kO*~sr8k=dfw*L(XMaW~CnoFQsqHW!9AhNVn7r_{ne>;W9#fAK%g*9jD0a9_ijEd-`x(Iy8@r~h zO~9R6myzMW31WP01R6nx%J9Gdu&m}+3xFlnmL(Kg`2t?rczAIU)yq?kEiWf$0;e8o z0-9*j4a=M0A_?-5VY*)t5nqeH5fIQVjCx3lMMmPLgLC~v zF>_K%(cZpAZkEZ#{=P?%My5hfHw6f&(dfo_DQ1s>8M_k}Cr9P(-rS(%ZoWOl%EA(a zlqpAyC%9oVPDv|>gbHWz#s(?kTk*{EqBeMDJ;#7qWqlF@BestaO#DC&B1;mnxqCJ%2W^oMx-Ub{2Wrq@$Vvb!LpQ$NhD*7CkVKIc}VG&o(qn{+_(O<>qDt zS)$vwwZ$A|y7JQUpXq5xLXEXK2{P#D)GIRdfc+c5H!}hzCRo5V3;sbnG1;C64llhn zre@?)@1x^~Mn;TY{mknT<9-CdlJ@(5_85ikR|nRXrd+P4h?x?RdvV-w zu$}YK6<8S^)C3%^w@Wn*R?DKx$tT1QN2_vVkpM@kZD9dS$VR}Dpr@-#tHCCXpU&i` z^3hhhr`yq^HU^M~fA<6*eG)>KkKP{Rpzr-aVke-HXWHhIt3BI*7KJz^Gaq;)T zrZoPVtqnQ;>lZV+o|5iSa@3%-w#5A**&&pk4N}NkTu%N@eNF(>U^_c|P0cju5;=hk z&&Krd9(AE2#;_H{zDf_E%2&`X|Ad zy0%2QIWg({uEK5CIF{v`H<$F9a+d-j3(nT^SAi(sSVK%GwY}6T?I;eSfy?)6f9IFH zh;N18$bYd-K-P0|fGKEU7fjm7A*L4~j1|nEewBT&q2|2YUljLr+4&ccle34$+K zU5&A6e}}IZMDm3O4%bDkYp0;+mJ>S`1w5)-Vmdj1PFidxSU232GIzB$)Pbg0M>u~12ic9eI>jy*b2KX}fH}#+#KdP4ge5^Gr;m>_)M!ZvN|^LDXxZ5O zHl3ZF$D7Cl`uSrA^DuQZbm&zh!iMZ#UzvQ`dM3X?`JQNSy>}G!W0z zgl__Fek@V`#2-MuX=!;*FF}bk#@hcfW(JsmYu-3~kWZF8Lqxp8 zxq3bwHhCO2iYk76(y9E8wX+DG1>3WrK!o(k=`j*YFbf+x9ZsH+ESQ?&11j*;p%=gRNp5tx4YXSAC^#6>n>9?R7xI`4CL|7^ zajbR|U;yh7JgR>X#A3ekrK*Uh)91YJ#^|5DPIS^Rr9<6r5s%C{_(%_gcbR~x8GYBm>y@|yu?-@{>DxW}z}c)>+!dYh1XMB%xniT&#ei##zQ{ae>_|a_477>SIng z+p`SxOQmgP$&D9tcX!@fJYdsSem`~R!A16^7|*!35xDytot>dElbto~4XPVRqQb&2 z8ZCA^A-$0%ALl38czN+L@j9mrb-E|rr#-iS=H!sa{B8B*1Fj{_T{o?>L@_zbVbGaw zISb_!?c54ED6=}gIB*!;t+_jQ`|qkQBsi4q!qSScRlHBZ`RaVkWJp4OD?aBfxj~ZY zcLNu4cJ^sS3nMW~&okmFe%AB*LD`O-Tu`=;O+F&JI!3je?+>cOt5^1n{HzMl zr-=@nnM2=H6d@Ji+Mj@3t+2_;t2!ws)QzDAuK7@@8#R-N7c#R8DN*^C_D{IR0?x^e zRuX;wt$tqWm=QBzPbBPq$HF}fL^}+0beat|l6H2GjjkviGqa+jot@poL*jaADgT;3 z+XXu{pXo<_S4YQ_7fWwJ*S~NEFHB6prT}~w%FQ^2O+fHP4%Sqblk@)cBe+ykQ_00} zCFM2KM`N(Tj<&40IJ26!j2;4;pO=+Z^!4;yT#x4B8>VA;k5ouc@A{fAJj88hVMhjx zIMWDoV(5y&g&akbnbg{*1IMhJ<0djC5f zta5N6DUcSs4d6xgt(@E0;)=k;!0fkINBvB`)|bJQH-u0M>tDhp|JElt9f!8i~b9)y};8wGkt5K)@5S!WT zeU#=%&StxDnhPiq|o!{&JdTEiT23gXc`xnTS#am#m;q^SWIU|}kv`|z1T4~U)I5=_C zeiwiL!$a5uNI-A@WSnX*?@g;~FHC^C@z%Ur$->0SD(3S#(8XqA9WAt328TI~{YTpj z>?kmuU8nKk_)kVn?8hF$rKFjXn6{O+1_g~tIc}+x?5?&vc1@2m+PGK*2VQMPd-MDX zR8gEx#-(7hl}R#>Ze4~J*?PKr)-!bYCArCh$+~0i6kIlgv}baU*Z*z(4EFVfw^HU{ zV`t7|AhlJVfoAtw>^6DcZ2~_#Dj~Ow-*L~yUZ<1o_W6fwH1}Af$l%JZoe5R+JL#)H z96!UM6fS!R!d7v4D|m2hL3tcA!Wx$SBWq_-pH(+7qZl@c(Byw?XJ67LaBY@;!^Krg z9gt9iN6QfE^7ZB3;m=26pDH+=7ybmOh^5}6`6>7d_Zo4~3*N2j)`F38NiH2P4IJYu z^1&~=$eXU*s7H3T9}m_t{)-AF)AP5VPxqq*gfcV|fw3_K>03^Ac6xSpeloJqk-@&* zaoBIM>`gnBF?B5L0ZR1OJNF67fn1}3K4C1WlUK>!oP&}&_Pn*GlJv+Dl*w32gLFTj z*arvI|2l!SOh+b)CYb7*tYh>d$aciRfo-xU8oZtAqZ6Z3E|j5it3k%*GS+>c>N7z( zChedx06PZNerh{`G0-=#EXh*#!iUBRp;IS%Rj(pwqtB zM0zz|tCRiH?~rV9-CVLeKpSM=(b#3>o~}z=3*h15-WK{`4d4|HoRp)SY+RCJN6!+y zk`b5;ggUO@LaNPm4S~N8AMbR$q93hB zi}41aPntdVDA(Sg@=TMQV+oOZJvN%}d;*WI_oH2uiyPJzNUk}rNSEK3HMq!XqiDPT z*C4Bn(7HMeLNcuuX*9L!9Os>idw2!H!-KM8Q+@^P-Lv z6uDpm@Ku{Udv7n@e^4Av(FP8E7a0{b#${Mn;ZNdsQOwgbYzIdtX3CSfGzdh>Dik$U zJCy*OoDM_4U{k9DR^zQ16~CH4CPE-}0CqFu7`?h40UeAlCr*-9-Nm1lOStP(g&f^+ za56GxFzOa66|>nj?z|xI#K7nF_$^y20H&({n+3#Yl993byl<4HBVTEt*qO@8!YJzj z$-X@vLZkYf%1T8*D-F1oUguCmgC%)z_!y^4ip9Da$zuJ{^o?A3{@0rLmw`ujp@^8*;juzOj$R1LJ^5QoSwgbb~&gybYj+0b>%-OpixW zHLs4A&nEdX$@L4low?%!l~kPAe;kfK32gxP+qq6QVO+mqf4`(B@H%B( z>MEINHiYsy=syPuDO!MJY9S$CE`rdLjpj}>O{AT_G0Y(+AH5E$ha(GJC7U}&D*5-^ z2i4sVRx*_16Pi+{4%5fgsUmM)hxWD*!o%+d`?REPCH5XG+%3GiR_Q+b7Vah0yIQY> z@8xm?1nu`P%x|1^2tmnx7Uu7tQ&oi(96b7Edq|x${SF591@=v0)A8|?<5ko7fR)p^ z`Fns8URLpEbN4&!9T}DS>gsSpF!?!8Oi96lGk%0;HGc=ArZzpdf$|nA_fYs*nH7<7 zl}*X9ED6VW&iMzL6Y?P--nqMRTYezJ&YaoP(7-h}FP2OjQ^Ho4`GO(>QW1B@-d#2W z4f{f)J5Vg=w1R;NC-e8))K>&zJJ%AA3CVfVt_u$fB|Aq);5g{1RMp8^}DyiJS<&7tJsa2}IhSa;ZzRE7xcoccTH zEq^wctx<;ethbpOov|oABGLFm09r|NJUk^RZ;q^zszdBZf%%jIcq6{@b0nM zy7bI&)N1tsi1-W*r3;9-dAI?wMl+4CJ$z|R9If#4p9LQ@{uZ{jt z?0P?|cnW4@TnhAyT^Hu6{i1+%%%Ia^U}r~4PakpH74xc_(C#qwLqhArNV7w3$8B50 z<@x31LbLPL#msUJiiM>m$=%KhWc%%B0xYa<*k$5&Vn?RX;GSl^Wp?rFuh6eNPKQ~9 zkC$B>BSr3DhzT_24Z8(D07}Fi0${hrYVE$r4B@_H;*orA=TS|?&lCiG5c+F=UdYAt z=s~3j2o#QXYk9*pALyR0p=5jRU*{&q)Y^aami>o_7TrMQUN&JyKp!6!RiXbS7bLG! zv_C!a(Br1=a=UM`hU3iXDq|l&nws(_v4Bzm`k2)rlf5@`kkBy+TKI$1)7=CVn*EocBFvs(#+>T4r003L`FpwsmzIU zW3F00#2sJ&1JTY)jh@Ywg}x_nO7B|cjLn4wj*~8&;*YMk?gjpqzQ}nKc|Du-?tPKz zGNy+W{$7HeI-+P*9ZL%BmZ|9KN2K9fHdM%l^RMf|zP^|0K*DVWNCO~6D>W(UOJ3Xv z>yAPATaM{uYr5{l4LC_nt2RTrn8up#9v-By^|rRHMjR^29tUnZEKw>G1FrFLW=SFe z&)Yuk*KP&|j3gvX0A8(^Ay4}uKhG%Y=L)k6r@w}fHxPRZzoUqgij7gkA^J#2C?P*O z(67$O%`Nf@ST$n(4tLG!HT;K18M4k4Ag27z?4nk(^2JGv@LO0n{l@-rfMQ{+!s+d;Hys-o;-vwK1pzH_hIOl@pFrJs>NEDut3i6CWy`Z(si zVEK3uymtF~8nk21YofuS=TH!38m~Y@Gg$^Daav|x!ZH)56w};vN?66BX)w!_$yb5# zhs(_xHh3Z>av`wbID+X7WVLE@%b2i=2Y#(oVsIWi58{OM4$INYe!(H z1Y$pwNaP8@)TvL|UuiRK%Q!}cTAO$7;DhZZN(o9i{w};hph>t~+keoLBC+IOG~)dO z{2#V%=tM~8n~w6TsK4AUzla#j`jkiffgD##+}Hm;!U(q?vEiC8rfE_88~zQr4mMwe zl}usE>k-6l{%b7%NFZ}ES~4%{pWh$ggP^w*d-Bif*j{+69R_nH*W~hL5=!O!Kchh*(%?>FAKiPEPVx7#Nc03yA_dt46|zW^>cr{*j94 z=e%4)+xFiS#*0f!!dsr?9kH=WczEe{T&ec<*b3U@<%Q@F`RT;ZHVzJ)6cm74gCqMM zn<0x`z|A4@vlBGS(BV+B7~Jw3TiBQ94t6@p%8Du~^i#~t-;pe&qz8dYBd^*;BN2%N zDidC>6M#E~So0zOz!>8wvlU==2`faO>i4Rz@I^Q@|?h`wncHo+boyQzY5t{K(DHd=lk??9GUFrDPZ_Eq1!!>>vU z`I+(7h|~SD0c+Cku$I65c>T zY(#z$$&*e0ktSsHH$e-+y<2=j=N{g4liE~J430D|lFo#!zbZW{dj{FunXYUALf>C_ zxMTFHN^bG0?;x~vf~Y%2o&DpcS~pp}xfLE*wYf&aI$y;n9v(k~WRFwIMo=k#uUJX; z4q1mi-Z&9Pc=8PL-wE6&6_l5!v&}zU!a5iE&<^a0r>d=Ay?Q!$HG};3bxy*8YZa0Q1ZGVzNbzhjJzDKLRy7MeI9%2D1cQ_Ix?S9s$8Uvj* z$A~qqP|;=X)oytYzsw^eUi2}qs!=h-vlfQoYHU85X@OlXnOu93W}{yY^1=8hSQeiT zw#Pp9T^M7nQK1~PD{LpALMnGdGPq2B_(W2aIMQGg=!1RkpO--XKy1K-i;Una$SAOu z5x$wDzu{%zHWPURA&`gfE+D8&u6X6iMEUeteKkpzUh zWwa71b2Al2L^5TuFH%gl6_5hF8q=aV5QnikLj6z`&}#(VToIcXtitJeWzX!1lD_W$ zv-%ZcA>jJ}w(o`#e*+EOvTcYhZsSu2mrm8E_Pt%{r%x@WANE?Q4{|*>>AnU=Ub;RO z8n?SojbYX+^q;{WUD`!aD8iN2$WwB|;c|BgXSzC%F{q&Yhe&WtY(oAIXkoB{&L#aE5#X_+UK-JJ?WO0 z_g>X+qnG3R^Bsnz3nnv7w@u~>cK3F$ojCjEDg1r6#0SG`6 zLFlk7O`H_MOQc;J%GqmG!L5xAu;ZCLJqH1w;EsO&Z^K>b{YTYvultVZ5(Z--3OP;o zj3B?*FNeNUJ9;~a{PS1nDt6+rg22>Paqy=27oPsU4i~M*h0HPjJpauJAs+WbNF&g6 z>;1>}f6~|2c<29*tgj4k@IEJua4<#|uZ7TlM1)Pe5E`B>%eVEQp2ts#ls{ zW-f(+xnhBXi)-FLba#bEA@3D{Z*y{HfMxu$98bJpy?&KC#tN#tGp>`d$Fnna1)53? z+G+kc+&1SJ^sn%S{;fCPakzI}>OSG7YeX>!q{I8-znxXLa7Oa!i8@i|?h#f}E*|`kc%b{JPZRe~FEqIW~mF8e;s6 zt!4;OInsh7=R-rbC(T)ebiL~%lBla!VWQAp4}>1Kn}2aajackT?PIrzy$%o^=4ar>hssRZ#Qtm-F7kDA|>c4NKw4mGyd%73>3QHB>voRKhr9vIZ?{xv;Wj$kKkM(}5oy)>P zD}bUFus2|81sV(6fG4vpf{(4un)8s$i2VVcoSa;(Ug^7n^rS}{zo4LJPZk+T2r#ff z{RPMzJaa0U+yUHLLjwcf>$AP4CMGYhO8}2;^hZD8fVpl}{r;T`s&&B7At`ASpiKw~ z2ndLY*=`&8eqk?8Yi+c36BxYahKISu#0CSrLZz}aiZwIJvePGCVg$3}`Max9lQpbT z&r|SS(;@n}S8%U)mHmbrfrfbWpu2{)>hBo0 zP-7pg4IDJd5H>dU$vJ?}Oz?o5hKRB+{K@~-0%(QakO5L)tJ8|CygWX~*+nJpVHc>> zykKcDA4mZTvN6x|-RQ(hGLn;lO9MdBjE|2~awcV$&P?kKI1Q-P>H)RhyqS6jCsjC5 zBmleNMY>=X4MmZZLOfBM2@G!3M>dLKv(foWuqH7f9?{Z zGk#oL23xov&dV@fruhcd+I<#~sWfU?9=s=#zUxz!Qhq(V!A-VWy_=~?+`LG9v8{>j zR<7zOnWai7@6|Pq_%LTYGt*?Q{ZTs$m&3CWCz>To7qy(JyYp!%gIoKR<^0G0SO_2d ze!&9XslY)Aj;gL{;Mvp$u;Cf{t!)gE@!w+53wU_^RstLd#!arkuv-{Z#(-%La1sGR znAcZ3^71B? z!Q2Z=!+uMhVbL@~uCK+!0wa>@{Cch?LK5Uh2K-USbX>-5?1_B<41d;Vd?N#B5@1g+ z5%~ca)O>T-7IDT$sGZh_J5a!?A@~7{{tv{9Kq+$b3kj3 zyI@+!Kx^XP&|A8XpMJuj;>LzI0qb14Rjz}2KVtv`_EvTiR~ZRhjDQdQVLV&nV~q7* zmT4b#F>e5IM(n}*65N-<#taH!TgCRBv7j5{AzN&>@H>IfPuy3)&T?xazFZXlOmcS% z+HRh(akO3nPSIB5(bx-f;)m(AKZd(_RPMRfzNYR6N0wRnawaX`R|lj<$+6yp|Co`K z7vl!V`dmk3gh1>ynZ)Z2=G+0SPK!qezaJPA%3zTT)p;S-H4qy1{DHyw%9~mKnDq znPB}A3c&NvVgNXv8zY!%={WWeMyPl-Kl(^3bFTWsi-n}~v#D~U)Phr_h6$dH;{%d@ z!ABQF4(6T}BS?mW(<+hji4!I1W9oaf_(UmTpN2{xCPW!!?T_pVE|`>pGPl@@NsPd8 zDTSByR;emt2_KfGc^hi`5&s)%k4M%A^tH+iyq122fC=Qu=&S+?j3=wBxi@>5*mnY@ zvgk4G(if7=Wo2Z5z1X8U)XN;rI0XjHkH0q-d>L-@1+6C8e%TO%*y?=u;S+nE&=i9qOth^Rmm=Zzy>q0{s~a1OiX+& zJu83?aBXQ`VP!`CoZ;n~Ts}PUK|kAL-D0Nw4k6a=B{BrJP|`A8&grL%wDIM;pd};q z_2=fl%1YIsKq$SXfBG^Is`3LO_#GWt;N(6zKOatuiyH%>4nWm`JpRhn=?(!#RygII z6nb@2-a*R(J_3xVGD&!r!Q${LxROLC6l8*ZllD5T)*Q4qR8$#twfyI<9sqTxr1ULD z;R6^g#(8F60ze7@s@~RP-9|6$uCDuAil=ivKy9OqpIeao{E90l$j-v+Pei=0+mI~N z+7%v6&3|_-`cL2Anz6HG?(`CXP2@jQX^-3&Goj^ek*_CuRRZdXj?Eu* zG>sa)4P|7;LlgmNQB=@Fg14M#`ab5s-F8W7iDryj8#O76!1uWtve8jQ#}ugki)(i1 z%LS~L8H_+rSA&%Tz|mLI1I(2q>0VJC6cx%pL6F@GP@zXowG~Z)RY_0g-6OEhYO#IQpd6d`X(HRFSIK&%QZ&4H`1F~3#U@h1m$DMOF81$G)a5W9 z5#EcruPZ@8Hw54zi~gY2e@1t^^tM)1794CGoN6uK3Rjxayz{47izdKzo0%%q%YM+{!Mwi94s8FBwN?l$r^z z5hHcIU*n{Pz$di<#Z2UdTC%|tz&esaB`;9}z_jh5j0BH4qGbFXu*YmP=(rcWdwl=0 zA&K}7(J!docJl3B5%ONQdRmP>%)iUyGPAL#?}3}k{(TN zxqhQ--*|vgck$zMCso$_w^VxU318kwc`Nc@+)es`XPL7ho<;yYu*eA-*)=+NQ2d46 zh<~B%!47Rzp>^N1rVVxPeOanbRJ?@PIdK>2Jwj2QrPlOEr z0{5uKrB2DPojJT1{98g4UcgT!Fu?ZbQg8NsK0uG1kNr=N7m%0HXuSVE;!S4si>nXW z(M(t0otqx)Oq6^Gkhmp$v}1k8qQcPk?Z+gPc>BPeWC-&wjAUvF&Uyb*0Cv5j&ZI(* z0GUs~cN14vPhVeGL`G0zxshwr1Amqx-Yo9C{ezxc z&m@W8B#cXNF8t90Xr@~=E(H_g3tBPH-Da|Gz}v>4f00GZa`iKtm|aEd-iXD^&zV@# z{~+<;Fnvk+wgWSO1N`yp$?8Hy*{3rYGH!h{SuW(_0cuxr+hX}|mUasD&J&S_PVhk( zProYgF+7X_U}L&T5%7h$dj3ZO0pl({XrzFl-od;fvAhc%YMiav{JCkT?+z?6!$I1M zA@%6L0bKoat{w8d;oWFvwY*&%k{F;W@b5F8<%6?eY2d{JFGa2wfl+|T4VJqA*U%Zp zKXQn<)}H^K{!L350LC7Xkxe2?dSXvOUP2o%!w8;>L4x}%6Xa4=5_c^9_f%RU72h7pK+E0-X#N-DSneVOZ9Y~90TYcf!D8iUimZ$-_B_}F-T*R zp6tUtaIgMl6LZx+Tw@`@^$$Lvj6T3NwgKKC*)`xv*>>NX2?lyztdf8|McrO zuH-*v27sMua?&Hy+Yb;w01`et=D2pr>$}HcbiVDPr+5Avi$`KU@tYMiwDlUpHv4J? z12rOlZa?*&xu#~f^?cq(g+zt~Q!)m|{Fxfl?8}!ste>mSL#xi`^K6+z>@5{NQqf$Z zcvdO7k3Hl$Fa1i^oLA+8JA8AX zl)M?30g%!Mfd8^WGNUclmAbVuiU&4UnhB2GhpQ5a7Lt-A>vs-4xnG)qiKEUC0N)45 zJTN@Aa5{l?5a$T^%U*%=COiN1esZA4^SI5*Z^L-%T*Iw$?E**)4E8&EU}FSyaaW@R zzBOmki-?FIZ?ImF_C!#^^VF;i4AL~lwM~TGx5t3L1`s%yYlNhB*tom9cXV`kd3nXe z!~m>Pc`AqmT2r6qP~I-j ztW0b`BGVyoX}QU48-Qvi{5md~zIN+zpyV_Z@;_Wo_c;f4?FY=;Jy(R(Oe&WR8ii`% z)dLwfD-}!6=Y0_1^8k)nTB>M>c&%@H{qXoWhxU}0@oX%)+F~$0+V9~pyl6ab-9bc1Bcy0-q=v=TV5Nx9W zE9<3T&Fw3H&aH+!lrV{$N)uXmtE5x|Yy?kEc87os`8O)QBI#>)l?;)k{J|8yY74j# zTLPD0+R|fE3j9R0xAa4^9%)<^S=)1Zw`?;Z~LFI4{Y&b+KPirAh*P5~PslRAf)iBkQ^iwnhI8dqRq7D4Q)Pz2U4>7cJb}Ku zUKpHf&dG+_&s46gsN^>_H1!rZ?`)4ZdxR0uPL%1RFXVaShnn1|_bli$GBRqyfvu5f zz8}pE9YPl#{f14A_u0q#0mIUc;uI_V95C9Jrw?eQCzRy#LNBAcx z`=s()Bie2Zo7~MXGWp782=}`04}#^>rW+8JXm9k?2Lx0_dRs~wpc!d3_ERQtJb)LH-B&6o+9TBh0S7f+xBV9A_E_ol zeiAoe@gLntB-a*8QL#~;UU1*!U!>N#ZbZ?}+ELfr%@vt@^a{m``JTL8>+JxdGaxku ze%k~xO~4|{Zn(q>5X#rDm?_p47Y`6AXiJ2Q?0m}6u$(I%c|nG#OTKN}QD7jT2^Db9 z`J7~iVPay|s95fi-yOBUA}2Ejp3~Q+!^J9e(>mTs-;;DcK`c$9X~iY=<1#Y*z?E&N zqT;(p(Gbf}rcrBJ8Vyr{i3Yv0-YEj+I%e4phesbRS5y>1e9o8cSKkVU-SMW%G^M=Z zO(8l#V&7McV?G?1G(>pp@$#R=MSSxTZijmewPVJ;7^#9BFZfvUbe@a%=bv02t@UZt zSFk<>kMlzz1xrm17N5=%Q1jd8)|`*^#A<$KOXSiI!g!d{QZrgfgxJI`b_qBsSJ!gA1~vVLB1@A5XNmv&2DVj-s2Uar#qVX zL;#@5ZPpw|M5#;H<;-ktd^DrhYX_{iCW_^vf2Av{qn?nFbsp(I7)3a*ZQ;e4UE;si zCg1Z?fNli^9vnFCMawk1@8$cS>Aqc4fOwy>SBY`x*Jk4-MZJx**3_@FG%7T~7J5L= zpk1UP-$qXhZqR6J%}#}Q=66t~3MAvP1MJ-l3ueI`aj01Ogif>h030O{Dcg3uuVZh$ z;CIt-a+zMgz^UKFOS^n4zu(yCFSx^I9}0vx-d`a%!YRxY6Ymv0cx}CkM|HVXW2K-x zh$*4uX>)g=Z+c)RRlw|7p@8=i2seT#EX%x2;I>z*su~Rf8n?r|fwYOGgM$Oix2?_Z z?CcCA5Q~IQxD-8EdjBTMGd8oXP+cal>;6!Tq*z;D2Vxwf5~X^zmexi_^ZGfmYVM6z zE3#BmC00D)COJ7dECQg@mqqV30SFxEb65u!uJfKgi*@dTu|MAq&~Rdh4etX76)tMy ziqxn*U?n|Y!vf5$anAOqI!oX6J#Kg+p0Avq^8LF6RvZ#lx2jFG2_kSGEQEgYP%A*U6~^X z{BfiNUwbG@_xhV2n=XS$yrlsxZ@Ubg|Dq~8+iXGXg`f*(W?QKCN!(@Tb&!RzP~|U_ zM=AQfm@8@AJ&$=VH)7N_wxu&vfTvLp*r?BTVv}Qfj-Df^_-xdqZkD_5U&UqnOqK!W zk%oc$kzDMPS(pmbNG}YXePpF{gG1OLkBFpItUQH_53D>9^E?PxgBj*ls~TAdouE<8 zLQG6yy-;2dJ-?Ef4_tMIBT4@5`xuUq3nqn}r z1tP2_)(LdWz0bDu#*{0X9PC76(Oq6##eR@RIrlg$rLC@&Ur0AD3OH&K< z!A-Wz{Zs%|YJ-FswfbCNUvn8BS|~Ul&A0m8hZ`4Z6h4&>8!uEZFnQkv9M4?_^7eLZ zYs*!R*Eu%BaL$0#=;^km8^uhm&Ex^e^Hg4|-lJ5~QHSYEQSY51?$|@5AWmUJOG`)1tDBGW@*M3%ccyM4jQQ`&q ze2JWf*<+C?wp#&`dk%=*H}nE0)vV)A!4VpYWV7RnKa zrrl|VX;z_t1J+!`+Heu>qE=HGM}yX5xD6`I{!IKZw4Z!r)NnX_i%?!sd@haey5!e5JduC z{ugoZWT}3=(Tz4OWK$1HL@TV8P?V&_CggeW0b~PHRc0(l`H!xEz7RR4ahq?WQR@{@ zO&Yfu`%s0UH=&SHZknY*HyzFxNkv2@@~K}Kp;4?AnLh##;z9`6Os`%ZZyb3!yEv~h zeA@8WQtelL*sJ*B2TU6!{Z(*4+AQO>9}-x`kugDDK&QH7+VQ;Oro4X(9RzBog9ihcI{7q8JX4M2ZuV_#I~QR4ei+avcOJ;0{T zSA0d~dANKDTn(CCw@4p6Xoo1*N(SM?vts*rHjJ8eW=Z23w|I6O`9N*wnv}niGFWy1 z15nfMDCYrd8X6j~YPH&Yy_zgRzfvr6qwTo}kVXKr_&Rk#=MO+g{i|4#i+%!HecmAO z+Kd+g1JwBs3qxvZCl*2>p~%E88_uQY~D*H9T;uKT}Kq6uS5 zVX7;CZg2@cVb3J93VOaw^V{9s1sT@SC=$x1O@vwuIwY4+pB3~x_&!wezAL%e4dJ)7 zEaM$^aL^GH9DJ7!kfDn-*C4NgLwkPhgTVkdH56Jj zN^oKxw8NdeR=*J$9UbxI3-i&jL$4h$LXxCLEnOVe;5NjZ@UNc~s*_7xh7 zwkk{)b|;_~3buKKT1ct&9%JHt;dwk!T2rizJk>6KIMB$+7}o-JyvK8pc;yi!nrv#K zOLAkDaL?4|LJ8>rf7^fM4`Ep|L1%PG)74OFHVl0g>t|Wq?6y~TkZ9bCi$nC})u%%) zm?O{oc3M)>U#HiSzlwUadgr9R|8d!JX|A)gOdLtt9xrCY8FGCG$i+guyh>t!78aoE zg8nF9H8s+D9xEndsv)RPF%HIh*NHqQ7oP+@xV;~Q(+fP!eUUPRy(+KC?6ID0Ee$Rs z(<_dZ4mq-spcU_WzP|?=mYzT+Zfi90$e3!O+JXx-^09EwfaX*gI3G@rXC4f9DS>`2 zn`V*k-t>5?fP+RM>2#i=wmeFd@TZcGPuQf*_lAZcXz}2( zC36=F-eu%2oR|oitiH8Jp>A+XQ0K6S#PT8J$-yfARDEIo4Z`2xzJd4C3?a87+YWW6 z$0`k1zPw)dCathy=k6T(O#jSi_2$-19I9`aS%aJo2+UpwXDY;lOPj~lZsQrP(95ar zC9Z}%<|%dq&*{FzVU-*f)%4TTNdwA3LPA0B-@OI?EtLl1` zQ+o>@>e3PIS$JceP5h0~cw1{dZVox+QxCFPL{4lDpQPGE4cx5%alCPGBoKVKz0Ko1 z_EX(r(EeXd@{Be>i9`${{-p?uu3DNl3j2>0>em~KPu<8gyc6_=+~}aL+aoAB9bL}o zUcYye+@J9zw+IVuyZUZ=wP9>KUFFtSx5uj#BMNyW;c&pHl=fRWk0+V6+P3T7K4UV* zhlCoR9-dXL;6Hv_0{63hV?n{dq|=3xCY;%ZbG8*n2HwQ)n*h}Giwp#loQ;}zOVtbP zL0bvb09b77hcY`VP37Qg9?FksZ$AD065}fAbM2m+m^cX}pdVYxsKImj> zFd8<4JWXvP)N)+hpg9+u4-=&`G-AH5pFcM=11CvI4E^M5bC0D@z4!1N_oLEj{{B)7~ z|IUp>{0Boy75xnR=N3PLoTq5=r)2rH2VyR#cC1)GdIa9=vG04;!}N`*Cfs_w7`WY{ zM%LIY2Ga^3k!yfl8C)xG`CdIjaet}BTsK3NQ*j8XX0v7bz=G$q8wuWaJnK(}TuO4R z6#)y!vW3i!_0pOB*|xbt(=eJ4)U&@Wf-XB_Wzuva#?5{!hdFXxX=x2VuX*V#Wn`}XFw zg}tLAUMT~z9g|8rRl1UW&&9rIIqKDc4tW_Ics+xxP-SQ9q`~!2YEQ_`3Jo+ZY;|Cg zPLkd(pq$cqeU6yyhiNYjqzW{i4TBC=R&|sZ$y75MqZPk|Q(fArVtcdE)`-mlqbl5!k{I@_GL16O%3FSTC%ty&jQfSPOeh=_YgoLa$x_E|PUeUte9Ry|Y6sRvaN< z-sjsa@DSL=vdc7po4`XOsWb;+bUE4J9Iv+>Ufvvj4sa!AeepRb$*eH9zJzt<)Y%?1 zfqqX*qsvdtAR{@I&u~5!6xyCCqF6!eN9Ufk!UN9JpPo@~pD&r&T z8|rk!II&SNx>ueLXzlHBSnd7|J+0xf8VSI}0!0MLSiO4NL()8f*ka1D6C&5n>n0L|+JMlsGA?kD1pDRz7E(S>%`NY`l5!u&_h{{v!225=Ad5)dN zqXMs4JO4O^?>UFOOop|r^R%1m1Jtu?x=Sf9UupyJA3lByHVww-*e{DCs{{4IAvTx; z(mhvhpR=;RPoj6~;+o{9IW--BS26fU(+T`Y#>B7;aYbly{WFICOD zdrz8FBGf%OX6?ePDAusBSPGSVF4fiu0GcjOA<+-H8Pki3o12}z#SqmGvMD`_iDS{{ z=XoxD*cvVbDo<;@@dX}otTXX8>U2wZPV5GTbIeF^at1DUACs3mfVedOzH!5&Q8v&` zK_R@CR%)1M&*)wu-)w5kc3MV4J|`!aR>`A1rDBqyVOqr*dZlV^u7h?wMgg5ymR2RY=Q+*OC~OG3)3tl}x)<-=bCn~Xs0pRx zLHOUl4L%z{fAal@_XzUMY0xLmd?0zp(uqB?yz;0TI~0*}w-qCX|lMbpWN`lDJv1ORpCs>+xe z+o=>z@5aG&7F{9&g4`dmKS(=|91vwcT7p64#mwBi)^28ScsS;cnZk^f@5W#{F|E*B zN*)fq8g`?W3jj~u2LO~RMhpy*2hztDHYN~bLXa!GWHnuH{`+G9zjaIIIVkQAlfDR8 z|7AvK==lCu9|4f+Qb~I~40&kR9C$cu>Cg#{FlK!xf(er1m?15j?WT}f&i=GTz287Pf_iG zSQKnp8jbE=_^saH8eI7`G7`8IKiB*UbV%Av!IjfeBxD$13Ht^MZin8E+vcoebZlUH z0#kj%jj>EYMpkWhY|io-2V+PWQ_JXm;%CpO^h;JED?kPM@(2x)fQon>0bJ|$l}Exk znPI+CvTP(3h=hrUpqJm!(2)DE$qn?1Yyezl>H7G+o-!qW$n|w~ZLOvk5A@g1yD7={ zw5c2{EG!%xj6GYLQUV$!>4xYTpIKpYe4-n=g-MmT%Lf9xqw76mUmnH*vS=iM`O79)dPB31^APg{=0H*)>=n@?zE&y@BFbM@e zm8f}<-Sl!9R%KpwNg9e006z~lUp9K(ziAjIn8?KL)Orfq3fTXBct1fa=~4j}SjiX| zW+Lubksd5yZ05KBhH>!$2^x%^9C}SkQ<(}KC+gfke*^_RCkqG*vq-L5OZs3iH+ywL zx4Ow(?0ZPc0J%Yat5AEM*(urG^+y)&;R+f6g{sB;JUrpJ_j_@*Hirt?cnW`j^O%k9 zuTsZ+$J1N|ozs-s^tANkgZ|aWBpQXzfI)^6a(L|g)#%n<2>KpQaZ4k*A2ZPA1Bmy3h9=y~gSw-Q{hmop;G-)Xb2-qZ=D8gYaWl}+<;SlHi&A?Z3${{CC;GVP*BR}^_b*JrC zPAWOKAaE9I^OFvZ{;`R|b{7_IUSpdqF{&T$9F2IaUCh7dz9%l^u=Hc<_~Aaj_@JmA zHiN(HW^1!&k$wycQ~O$UxNW7+Rz`jM$D4h z$pv~XaU%|!c)W5O;E5cDv&}ZmEiEGEN#N8+M5EtEA6I`|$%kji0#!7T_M5jo6& zCI0%qb!vS$gjti@F5bkEdlchm_DJ2pcGtKs5l8dhI+Y~4+FX6+Ed3!GwJ|Tv)c81* zfUXw227M1Yr0;q?3J_{Tor_^w^X+ zR*WG6-S7n{wcu&>!b_{YRP#<7Mw2YT&R!xckCNX-sf=$ z6MK63fa;~+N?q&VAg9v(5CH`y%LyXF=0QgTVMq7 zvQkd1PlH{Y8{$UYT#Rz@*^Ga@R8~M6!fJue+>sX!F>Rw`k2B%U4{C9zdut}+HWT^E z_9G>0#RDZ8$y$;TzUM2xMWO3+KQ~vbpwWIC5US1D+U|3gb@lkox2ipeXy}{gTMtGn za!e~PBhVLSTlef^);aXKE>4N3R~h=Wv`V$4jWl#>w_PZa3Om^;yq06Z4_AM&=cUV! zrvhM(kf^2HFcO8?b>AUwq=VI0wy?OuoX>jPsL6yPT?FibET_?RRuA*b_VAi=_g&$m znWOkQ@3R;#MSV%?cN-LT^mcxr5_&&TMKk;HW}HsF*T$c{YfGLzTAEdLO?&LEIgiDn zTKzLxvD$-4Gqc_VwibBdKS6P>e9UPM-a==`w@apWpb>l)gzvgM?0rp0b2Rm>eDj-H ziGJV2o*&wUkI;4o@_l{GfPn!BFbI2oFup*wrZ>52r~HnWh%b<4ai}a?JC>UJ`a(O) zB=4lA#>L{@aD@h|sLS>nggq^=|I7Ar+Q%CiwY!;^3kr?;PL~3uu2zC z?U_*#`gmQx|5oJ>-;ZXB%n6g0YvKEFa8QfB;W<7oEVH*4MnBXHVxEp@ z&JeLciqF6Ypv<6cEXzgUl1kWPrvuw=dxD|<45o>Dwm10qE%eplO<&@m%X1bxgVXbH zs2`H^1+VL`RTW-@tPJn`luW|0kf5L@5q{nczsFg<>jkrM4#A<98fj@rKC0@&eDngO z>xgHT%N*jd`u^fK@%+~YubToHm{W%th#(el!$*{4(y3l22OTN}{_;NhYlCU8&8+9V z31O(C>ht+08HuTKs#Z&pY9czUaAr4(2}h-^-xrsO3sy`pQInxET7B5%$0wyyR;}cB z2Ge1{-Qw6Esx;f`avc^cwtsQ;Xjn@LwOYM1S@tgZ0G0k%f8plB<+A;rLUAUmW~ouN z2Mp82|H8bZWr|#KVoT zZf|6+cIo88^@nGgr{@g!Vd;YDKi*7p%zlh-cHHleUg%RuedRR!$IXUULmpq*dZcA- zDF`=;RuIIyie;@n#fuNS`Yb&?_Y>Jyn)W8vy|VV-sJX6>9qyKtJT``K8CyyD(v-gK zTt0gK`ZVV-f)d5+JC@Xjg~PTlec7|Pzw~q=FK5BaVG0qEh&OXW*tj!tEsczq%nYG}5yjHfS&rIy* z;!z+`3Zl|cAVnebz|Qh-5g%{1zny`_S=VTnsXJ#-m zGOC89$ET-5)g_3fH1TK8Cq6;pogc|# zr`Q>zX`umOE!7?VJ%E7UtR|xp^I0dS-DHSZrxfFj3wK9MP0r6}{4&n(x{WNk4c0tSZw(MdLxzMJIdn zF+N70%s&lg)K@rK;7yBoY+@1EWmK?>8yoTZbEbQ`hVK)JA70k3x#&&rn&MMUDVFhU@&==u(72$n z(#a1?aB($K1#zGw&zq|DqL*T%OnO7h&Iq!U?%Y|mhSfN=x})a2{4Yj#0rl3cSiKx` zKwi=)-TRcw@U@)H<#F^v(taGjf*~YBG;&=Q_((7@FgSHO9abuxLA-RyG^UZIsS|w> zqApi&&XG~Hz~%4(CFN+g=FFZxf1TaJ*79XF`HOhslFW~WRI|-KVbl#2PA-2B>cdOw zQk4DPHa-&Yz19lu^}zsfYix3I;rMi5llkk)nS`Swb38kuAgS&hcYv0N^+}`5+T!>9 z*6Rco^)l}Py{>RUP#^<6^rDg_H0BU2x`8o zIsXY;u?hzP1|aZVJayw!9_6-Lni>=qnH$)CPcklkl;wA1!51wv=hC;wQJQa-SmJlr z_6CkpRn?!tK=pW9MuFkIJtz8Gpw(f^dyi)O``z^ne5|D||TWUa{U@?@p}T zn!F+$@5(VsF`*~Ek5VI{aMUF%=cD*29gUS=xLgbbl!T8b!&m^-DNc%VJe&Tqs;E#Gba2w~jL^+h#M9AN+$sbp}s$MmH#WT`~ zIE9M1=Xxw)KFKi3>x*mkzI@f?U%Ndv@b_g%$IM&4{1O^R}-*6;4F)2-o3 zx$?Hi6kcktt zxQk3auRHolnNg$3T#6>FTt|lQ(rp;N{ZL!za|&A~*>qmBhkdO0$HbdDozDIaO({wa z-FMIjL%0;eb@utuxa7U6P9r1oKhkf^Rm|DaWWrs&_g~JPS1W|a_o%u|-$JFy@xciZ zfR}|P^n2{)apZ(6rJgx^`KPuxWuwuB=@plNK(4|jSR}fBND?&$+nZ^BUB7Z{fGujh zI)nLcNoi@VZ>e|7!H)d^#rUF4v^NCA(*Bc0l;{z{L;X&Ys>aVZ^3Os{lvC=MRjbHL zBYth(qhK3%7`iy=Svgw&el=V!MsqKTIk<>a@3g;=Y&L1A!nz&^z=wM5{S&fX-At+7 z_Vl`@xwqi3*yLGK7dp`By!9(addWtsT!WQo`OhiifZo4<{~Uc%n!LtcpznClJ#B~-%#u}SPOP{9CMU%@+?Q6MNSTqnIz2JXtyj|Fwa%-02~h26H^ z!TIt?b^KmJPJ0>hl#Ce&nSNx8-QdQvYU*YDRqx^EhHu7FC~ti1c>Xpl;Apg9SY`78 zIhX1W6#GzA_F*`OZ*9F#H^29!Y;=gkL6zSEu{e~inOY|5jhJo=Nj-V7eF!-I zmL7m75@4fIw$}7S)K>yOC9Hr_M(U2HzLlHiucGOhK0POUkVb(-uXwUVxyLFbToT;M z>?gCx`VhzUo?l6!aAZEX;C9NkDa$AKW`mZdnz}mcUCr!|;{NFRKP}xx=+gI%s#Jr_ zgqC}?){~l4@|PFuwAVq!!D<82Qc|=L6p9K;8hTt18mWyJYZ-B)s{8!=ojqW~{YV_j z^C<`T^ie0<$x4^L2|Jd*oGsQu=lLiH9L-mmo?ls@ett{Hso;y(g!+f5FggwtAVxXR z0owaj<})6i*d0AXCn)7tttR_{qC)7v=5Vudgq9sF`9?jZ2*E7kMH(L)t4tU8o~U>& zYHz3!w0)_8Y0;{9Dt}4V=)ayR-O9Vud7$u=dVI`fUuLf)y!|fs4uv1`=R#)INp8Lp zRP7X`_5!wJt2%yv%j}&lNpf%GzaH0D`)?=ull}TaEdbn=y%EK)qO%wISUAJkHyqXtxriw(oolQvNOt%C9Lz9m9oKHd z8&TzHapo`&%0eX%Zpk^DlE3=TpN+(wrrhk^YB_RTU&BCEh2L)CC{})D#l*Bx9<0B^ zlcV)Jo4dQV;m#Sd;xPhTnkStC#$vvX=<@L$;wR$h!x}C>S72LqlzI zKAWGS=ON-y{tz3aHLqNs9xAOJK=vzcCxNW|H$2qj6iGgdS z=n|9rzPOO*zn_S00djIIoyZCZp_R zCf-|lI9YZ8=!l2?0xMn4(We|94lyzJ?zT?XXTx%LPU_#fsGD7lEsgfjg=*l>w4DzX z)uwLYskN8Zd^v;Df?Rr9ztvd=CGTAFam5@8dG+=BpKPDFWGHtxrOww87zl!yd@a6r zn2!$+72kd_#V}WVapOP^N+JI73`fQ|@$W6)7j!W=;JE3(pL<^Vkj0y2YSl~;MI~x)@;E%mNpW|-ged!BRl z-e>P2Jq>6l3z=E`*R{XoPm12&hjQvfkl)?iFS#58odYPs=;-`S@1YWrt)nKX<-XdR z^73gPXDMdif566D`Z4}&qx+e?Jtk_qlbvA-b4F=d+0o%nnj$R{ihxa+F`i%fyMA*m z`LsK)haA5af8Cd3hj8v9nYvF<_u+G85GPGc0 z#?U@pv&OcidT@l=SapqN6D8)QTk1XcEV;YI5^#?ltgWSQ`zkyl3asYIY>O8gpa&0< z(BRnz7Qa=ELliBh7e40`SN4MW{A!K>DMjgVX4UX!#!{iQ+VX9|#V; z4!h&X5`GGy=G@=!j*%i#eIYI*bF{rpcfRsD!u_*N$#x{aNDxsl|BoG+2!(7}q0Z!X zEuqZWYn4}=;aRSU%A78BbmBO-h5D*){v%Sx*+)*?B6w1w8h-7A4(*t>FgN=-K15vh z>(dWYY~A>^om`w0_Jt-KU!B5c>N5p@_sM2oFBU}%y;NPU9*`DhL~L`0pu1`=^&}Qc$K|8 zP~z<_@GH7MYy6US@^9C622J>{1FRepQ)y{*Z^6k~n(_DYMmh4Q9oTkw6hFfSv%WsQ z=o)js3U)sS8`J(0M)Pz_3C=NodshB;wy#J`eoQ2&Ufu=X5~2MMM!D(2FvRdj?$Do#DLBbms)0Fmo6Yzg+^*P*`ajfw z_&{tI-9TPVROQCkKZJYPG->=`C`(j@C@+n$wrzG;8*( zo_c2b{@Jl=36~x)WrqJK-9_6ISO8{^-hS^cmrbffhr5(tXDP%_Pfwn^+HQ?{i)-V4 zO~8BoGz$6tACaBXFOwC=cO7R3HbCz@E7VC>%Cd=tMxL3uj2{xg=8MrEM=bKEeLR-t=h?3vbGKu|Mt)=E+)4Fp zI}N>Cx9$;B%B;=n`$ylw$Yge#Z9a7sMfi;suW^|D)@k5BypydO*L6M}k*{93zIC8x zXF7>9W&ZbmQyC_uWCXvM?ZW!{?uA&6g(?!wrpW_Le0n2d%9iI3rPUCu3hu1Tt>e#0k^UH4enMzy!!M@x2!>1JlRhA*n!E!|WAyZO;X)5( zD!apJ{vn>1*Xr5#Xm0=liPYG!t~do5jTZO4$9}D1zn$n{3yA&@0GB4@pW(xg(oZ|u z2vjagU362LI)ww>?AP)vFl87i&j_3wfdef1FpU*6kgK2Y+dqt6IbJVs`sWT19d73< zcm!b81iw>)`9!IGd)IX&M-z-5@O@{{p2Th67Xmp4jm@Siru!vI{n9(ty0p&EpcFRP zfz}3F(=)c}tPkhvjX?|VV>YY(gzTXW41Q^xy}ctwo~ve1>|Au60UCOC(LK0tF}~^X zfj>&%I?!JH9crRzdDE57BQ0fUWna@{WKJE%h9+-gKIUbyug?d9XCbs)e3ReG>7?xi zIw3o~mCIg4F5dZRGtg*}bZROks_15^H6GW)>kOM~iJURr+2)M(_3_MH0#r*P^WF-1 zo?mQvHAyM5exQ>toxrrlTjzB6eE48P4UW9<+Y))N8pT%(4VSvUC%+R{?*7izTczd= z*!MG>@kH5&V?r~{Ai1pc?t6FQkTnvP*>Cui=t$=B$WuN^sass+by{Ftl~|hNRVdsND=CA^3=km))-Y>qn%>NCrHq~J@)57ZryrcTc5@Rg`mLo7b7(=d zvWNS5Y*yRa!D}W--e4m=u6Wh$y0;74Tz0*n2=3JUrH5DEX!+b<-#yw(6}2ie*OOyu zjjDdP^nVb6;)J@39ewn(g!ni66Ej`twpFjNHX@*H5XpELR}Ado;r4c_H!FYK2OyrF zS>a{!l$2B1F8saERkm`nI~laMl3CxGe-!GoDz@j&WQnTy_0VD(#baSyVhuI(L8-}t zyTa|Pr>-t!S~`E!wtCWgsctyi5fvZQ*BZrCa-`&}N^rT)fTK8l#n-RJSX<~k6-PyBD>Q*4Ztd|%em*RYy z>LJ{ZmouqB)QSqKe};y-nupEzxuG(5-3ifhOBc{zWakfKP&0i1yHeItLY6=W( z49k#-Umi%~#xoDLBjV;Sci#fihN26*%1Z_Uyxc@J|V~EYJso83|70BhF&6vx|k?QBQ6UN~Be65Py`!|)_ zwlsi0{Pd>*@3{%ChQ>b-vKetfxtt&!{f6|}a@R_id^fkYhk>u?s!qEF9ks<2Z z#Nxzt2~~ghGv_`CV_cftih2SFaiv zG&w{D-#iu*(b=fG`gwlXyDCl3Xr55k^p)3gy`=-jh9Gsm{Ege&73`2jvAXYk2V;X0 z(CtP@(9~4dQ0q&Ii>F@v1hNhLS8v9(RkknEoG}6a<;^Jg)eL?CfMF$SkV4tH*mY^Q z;eK`RF|+!V$F?(xWa{cgtPB-TIbjoHuQ%o|0*~E+MPQ`oe;I z-OCS~*l9#R_FKPIdZg_~DrJh>WN~nCFdfJ|MA-h>7sfauy#e=-O+8dl+BV6R>dAMG zmHq^%VX>2&3;jHoqzAQjVL0fS+wmAj#z&ER*k;@~DkF#c<~reUexHEBpwXbw!0KR{ zhU%Dvlc>r)3QHj4Y?l9CQYT2~Pyc+LW{6!?Y&PyTBUAX)c)10HSZ1mxOC+o=2W@G6 zx^3u>SohD&Yv=t+>@AK@v$y&+(>ssXA7)*r=djwZlBcY8Uzv4`aaxj|hcm)>AV=z@ z{tOKTRh`e*aA z75ar&+wKW>6zON4?1WbCG>8Nw{V={DP&qShiw79ZcB9w%WUEf@CPO@b`(OlF9gG@L zt}&#fdek&5q8mffT+J!Q56zUta0$FuSziWCdn^RHyA()b_CbCEFi=~h92c2njd(q2 zv7D{^iv(4um>0bI`}^E3=FI=?%A7>K^+x4XVuySPhkAQ{9E2Rsm zxqOY94%gR7@2+TZvdxsA`2o^kx_67MO@^mLcFpd3}KZ2>H^Z!GF(~qtW|VeR<5OOWAF5DE<~IjCDfI_ zb0W^2u8g(gQw$paP}h;r-YFQHvip6s#1+l;%iQ9oG)aNNy(|U3pUG`?vYzZB?c~`l zjg2KzRTzMWT^OHiO+4~_{i=d<_~ItTE{(Cn>io_MOI=cB@27NYtIpNBwE<&+gz28U zE6Z=!J61ydvftSMEYIAnD<=5i62p}3SxX6r&ey;zgzBYNU-5uqgJjli1mYH!mNOo& z5goPF7qJ`4cdINezn(YlcdR@_mQYZ88;Se%eGej@axW1T{Q-^=)z-JfJz;(U(2@&) zP&{rQ0$JpH%>Y%)567Cz#e%={z8ryEqj?;%@yTfi6FI(-Yd`_WDcO|hb zE#0-jWn(tDILN+9T}dyInU{sAWI}b!aDAQ)`Ue1T(WdJ%EV}EkW0Wy4R;H@VqnQ`7 zhI53%Q`_X(G89??jIp@B+5~voKfIG|*&}Qo%SrUDkm(Qe^=-W1m$4fMNjkVol1#o^?S9lnjudK%Hcc}|Dj2z{p1_xld^*G zi^_rw6ciO|-FynXV+HRNvn_YjEy8<5FgLA}=#g!m+r0lXA}sWHDhkUD8O1&qqscnp z$VeO|4zWHTtqmMZt?k&nF}Pmi>S9n1+xtf40hLsAlN3?_Cb08B$jnDPh?pqv>@cq(2iyJ{rrKT&SyDQC+?c>Ox9 z^o7BBC4JRO&p`I{c3-3Qe(&d5Ki0=|>D!S?*TZEVN+gnr50Pu&syzun5P{W&Pd9?= z*|T!FG;L?+Gq9CK!|SpzHG)YOLUy-)%b9~U<;@9SI>ju>$x3wW$Qrwiw#h1^W*9r% zoILx^<46Z=U;qRnrNzdcU0zg`uYJnXaMq}_;iFj{JP_2@e$(g|4tg=boAcF^>=Ozm z9Q5@gxolUR9Uc1{e|g+KGMgwj%Csi|03iD*^>&c<_qgxz^JRStIyyQ%?KVi{=5~)c zZYyTBoSfFdp}=+82>O|r)6KDh4etsxm@uS%n#^=+YbcF>Qz*?ua4 z|H%9Nx9)VHjI>x+r)&7}n;FbOePMAo&})qJ3WAn{;H>_O{S+a;?ktBRWn=WeTv$@2 z&_p#12%gCBpM@-xStw*Z6=`rdjf;t)o4$LMce>U(*UV~hzC81(rs{B$J5k~&eyf`Q z@+`k@qRt*Kz}>y$j^BVdW4hhbU^geVMbHJ_P4#O3gWdA2EO`(pZ>DQF?#Uh1#&eDA>xcZyXzPw9aT zvd)YM1sHO5eqf2sU!3?(ja$tTk;_3%#T~m=^V*SiAc5uoWFDhv{@F9z@sGMhQ4{4g zpIW=dWTz&10al&nlF+xhrkoF~;G}Q05Xt%8tdSh$=?W0?0uTj{9@%*_=L&H(eAnY$N zP9!eonB?g44h;QlP^@cuhC9zM{FSqn$jN58YBcf`s8cm-guyy@eyR>^l*OO2!3atE zy_ol#`rXNBWw=ng6g6wr`k7rncz|Uo`1~6xdbW6eMp(ST+xekRLg10xBQM)LpOl8} z0O6M3h1Z=RB_?gw^8*MK`V4@j7re=_e<|M0by^(o9nStCOwl3{%dr{f7f#cCrMm*B zH3spB{gT~NAr^r1gYCIq&PdPPc}t|s&Mxl0?EO9;Z~*(QL6PS|X-t73mTjN&)oVpD zD`LNj>DtmMv}O%H8v)jiJ>JN9{!MxHWOjAPekm38^POQK{{HSWaA_yxj6q8TGY8D| zaVh?IP0h8k^>p6X{_V6%MRpojA3uVWMn|u0ih5zXFvsU>y3Ex}uu9R~?hl#}^ebBF z3^|YY{*FOZrCw*}dB}8R@%P(|`U88~+0&NZt(LX*%}rSVZDQH;o-2yH79@froqsNS z>$70iMBCOK&o@~dXBk4qN>@@S#l#sATp(OqoIfv^$2(CiCrWb^ECwWQ0~{~LY*(#` zUN`{KgqdTp`saDtsMFy}oykhRJH1xh?lg`3i_{5xV#^}w$y2Jp)+rkK$0{{?^m+9; zl^2XRY^y|rkht-Mjx;=H@Rl>mV4G4b0n^gDcWw^(JhV`>Pi>~#t zg7A1L5TNet9wzN47$UdMBwDOAj85Au(l`Wks1E1b^}yb)kY3~|W-xS~&y{IW<0Nlt ze>&dA&mfP1Q~CMK2IUtRblK--V_RHkAAl`!qS98-l19TWeZIXbqDCTx-Hx@x);B8R zu&`yvQ&xfK(Oa>VEZ;Cj5(vD*!N=d3ZL}6|NZ<>I=oWk-DeWfR$mh6wJW?PC{nJ@N3G80@?l69!FG}lTu?1?y(l3$D2hC7m-*}1TJj$uath;2G< z{lgi~-e^Gga2aJk7iu>~L(Ja)%^6O|iD`%$FRTKzg7tD(*Ig?96n{f4OY#I2rvjDLaOnMB;6+$-ZwD!9QedMWwIUq@o7bx! zP}KKXfQ}c6(lGbrWQU)qCdYFk;1sdZZ~mmw6Fd8Wh^hQt3T5-IJR7GI`O*@efVZ!m z^zdd4)WlYV5~J@yMm?X|58dBN9FF2K$ceML$yn3f8k(?K<;{K+?_rWm$atT5JECP; zaA`tm6jP;rSIB{TFDM_mfM?E*dPoz=B~JJ@MjX*1U3TjjS|cX4X3 zGz(bQwBU6*GVaaV0JWbu?TG$0??bA_$YK%$jXA#amZqi%?x)D+;VeNqLs%+C>dZxN zXO?1NFMHzZ)tfSZ*6*q`_`6TZKH+$Pu3JciCsll8e5ZnHa=Yra(nwknnuVTV4KW z9xMxzpy8Ow~9Bt$A4bF1r8)Y*_||qB}jhf3FqsCOqu3BEj%O5@4pvX zA5OtD%hc?=$Hzu^-1e6NI9brTJ6-Z&4Ve2A>rwOFVJAOwR~J`(HTUQBDz0AhIomMjhx&g@X4Tc z|KUZcT`7CM*2Q|L7(t+@#XkT>oQAqwNNBiT%EbvF#~1`$AsG0k1RLM;>(0N%Za@Q7 z8LzsE6z=ZHP$6MBQ#!?C(4MrrspU8dUaFUd1@40QmaEJ(y^{vW&?6q|0>KQ12fpY; zXl?#z-9fp7k_L-H zo;uj0t3Zp}(h`e>RVdu!=5`6ANGYN*RavRQhKBhu#N1rCYduNr!Q?aDdt3fw$__l? z6S-;Z;j#S~Ib`^zu=aZLkB_$3#>nd8&i^-2h;0@MB!F)(Ynd-tyHiB@2h zGkXYab7yDGE6>E)MhQ9HA1)f)C^u+l=H?>5C3fSvp?smhlJds78MD5lW$b$%`I3UE z1}&J$wNfp@z#(;zOo&l2QO=$2#Q3~C_^UDlLms16dK-z{_tV)E>o~IwH8>AuQ5&Pse zwv4#sv-A4W${n}MOYAgioCRPl!^2x$?@AVgO!3tgYua*0+ogkeB<+hQyUL0-b@KJd zNGjJI^$poXW>b@=G<$r?%F52SZ-B-_XDUmbVK$PTy5m9h@9{Wf>+A zN|Rm&Bj)1Jh#HhxA7rrTOfG6*=bEWsY0Yr1NQ#PyDP?)QXG8@cZm7O~X3tQ*+?(LA z?!Lk%8G1&9_$jY1sJe3E?$5X1Qo3`h-G|^n^#h zn7@!~Ce3TLOJAZ8xYB82?$0>O8n5QWo(&o)$QBt~hy^KFn$_@;gk(MHE4yFIAAqwW z@?R_+QAV}IRkv-KN@C%0S?b0@4sL%5S8`ku^=ckO!HB{-nqik?%thl_8@39yHbXGz|<#Vg(do6^08Cw zS+jZFo8+-fV@#;&STbaOd@tIL?lJ%SjkxBt>*R86d6~*~b;!IwZ*JXOzb(UP1kRd@ zf6toZr*dVjHn@hNd@P#X_!~hv(hiwPhY3^2(;*6H>Y9PQeGs%{30$^xoSdU@!C8ua zb-M3vP12zy78MmKloI!0>Q0!B+59ZC{}$x9zx-}v>|i;Bl9V*hWONrS;Kju9r%IJ_ zRpXeA#Sb=((de{UV>OtSvSF`=h^-NrCb} zd?YKcsOpZcbASP_1h>Nlcfzv#V|`QKkhF3!e>XMFDl^{nDj-FPc}%eX`9fgk6FCD3 zve#`8*O-`?aFv)2WjK3Fo5nQpICHIylOU~b;UOUVkAg`6i{_SMrNySCkvJ-P|5kT~ z>v>}_wfG(kyGsARY+VeSIj8&1)>+VZ%~~s|h9)Vr$mtsW1Q4Ky(J96tS15dB-IvJ0 zPlV7&k?|SwjI!N;)g+1uAS#sDN-_GgVVSmTFV0WfyQiF;9W>3R^jT_Wn}%}~m$J7O zfp2k|s7iq@40`gL^`wf}cqWs14acC@+U^7gmgGnOyb0nhE_XV)nwlDDwVj=v3A7P< zbPz}cydTnq4W9Ez`yyr#Rwa~p%X2dP{LYI5pc0af<49-i?zVPIbl`ga{FB%4dDSie z6Yw?d?(TX8KCW?HOAmLyd^u-6S&g-~t^#@mmrSpKnDebY6+p>AOY9!G&%ATraMv|R{#W?J8l=nYd*8; zeyLt)P&>44=D3V6c4YB zkT;YMulW{R=S0}pN@4n8 zs$*_-tkg9llO!PFVk5`)D%a0HASqamk|MawOzCbeO#(}?(TlQS5>&IdM_coEw`8?1 z4lu1@KJUL*_i^qugS=^d@tsE>IpFK<<@_4hj)K_#783$ar)&%T-5xZG=~3l!3*TDh zGqj)?UfYZoB$3TXPgl5;^|}FWF!KP%pj%J(Nj{91nGkTz<^p{(J~A?pC2w9o%WpK0 z(@8IsUxO*bzRc!Jq^?Lg4@B|7)qMrB^dB?=e4e!y%$E_4cj|RZ*jWKhQX1m=$;Q^2935< zRzr~R@zvI{)J1P>Zc3X|MO@X+j|2<)we!h{pPsvuFsc@=x22&u+nMGMCkA_@G)&XF z>Hqslp13_Q)q@rKTjTaic+GVH(n3N){J!@$H#3rw2BJg}`YO2>bbflh)987nDluPo zkLJ^ghR>H)yuqX!zFs1#^m6-hH)#%2wNS5+(j?WufP8g-z(xoqyMv@;O;X` zG6pu`1?O8=A7{mU?_$fa1pK%kkzfFx>pz*%+)ws43dkR|Um^BzGShFSss_*);nL&E zM#*Na$$5&uA%N5Tx_FNQ9ea!Y%4u7TKKJf8X(y-t-c18v-Fd56`UFm1u=QW2V`^dkPNC5u)D4K{A1l=dy(fGD1 z`@t}n9G;mI>1O|A{vB56?^t;2`=q(50))TIUj8t@pkcl5zNmM;LWsP_dcOE2!iY>j;ttS;}Y1( z%svrCY^aX~xwRMR<;@gXQ}a)sCIuy9&`J%4XJ=<8Buqmr)Psi)qu+s^b#)*U!}rH-miUeXoB&!>8B=Z|E%0$dXfBW^tmj}b=|^)oU2 zOPCYS#wHqOk_p6Xlc=YmHa}k z1l*|GZuVp=<%amoqa6U~i0X8!t=tdRNig$YihKEP@IB~>e`DY%*NH}pbS3<9I)Ik+ z=}QsT%~&4gca;Wxsjc8#1-=sB;^L$*wdM&qES}u#S4W!#>oV}6#9`F@K067|n69w) z76#X;La@~ZXIEql4!A|m&CS_EI~Nr-0uCII1=f2H3J^fgSIp}!l#28^!HWaDGB_9+ zyMb1Nq$_AWx;i^~t>#6+!NYJ6ThThrbhK~*{3MD^0LA07S^nvCU_@gvQEmwaQq*98 z@#akr{MzzzaIN8GjzdJ#%XPcKIX_qeT41J_rh*5zcR;6sOMc&C1+GfY^04O(n9n1x0C z>sUNCSOs~5c%aXP)7iT{*iz#Ub8fM1-Z@|8JxxM!IyQ2-cmo*7VmB0u;1Z18ZWT>O zMM^pospU4)r|*~K44v1@jhP1T71D)j@Xkp>@w0~@9kpVEmn>QpR-ULcWZHfnGI3l& z*A*z~U%f;ce{{BnPt>|Pw*?v!qZUHkn`9CjMcr=SGCO;0O${$^YGuKBd?w)wBON$C zM-9Mv5&A(eXqKSfD>WTA7*t?4H{XKPG_Y^(>wpm9DvOzG=o|}k;^_vl4~*I(!E}ij z7gyNdf};N(woCt`EdGTt>_~a$uAB#^XMgKGVi!LkhVHVf7ChxZirs|0@U$d8vp2y# zTJMf#ke9E&)aMq)cs770R%yk)xJ_a9fcGoEtH*nTCAr$&O^)K1EA(kKmX=1>*C?f8 z{xmm(H_LNI#-Pt*Wm8W6v)Xxa%t=p<|M)(n<8R4RD`ObmvKAH=Zty~<#;SGPOMfpL z_FCS>Wpkne46gbcZetRECFYGWBxPf>13#e&rf{)?q>>({g|0BVNE*deqgt@5?A-zz zMH&XRN}CmM2nC}-UpaH94(2*P&o$!*Usy;xKgck?A~ZBKEM$(0QQbX)0jvIFnv+f)A@fK{hD zD;>D1h)`QgN=m+Z^*J{;_x;vm?BTKT@%F7Ps=vsf0#<{;tiieF zAaHZBI^AFCisLrcj4+Cg464cFXD_s9Rr+CZN@sri;u*obSh-98TRjy+}dw zM}R1!Y3nHqEGiPA7?TTC!})RTZw00SERwD?m$~lh%F!o{J=k2%O4$PZtWWChl6DFd z^>&O!O1?9Lgx*ZKwD}L$QKafFRU zJRlBd&j7JT)+Cd9BdhRbqqrhQ42Ak_IH&%RvZnoyl=V9D5cKhb>(3GC6iV05ygXcC z?Z&eadH7V?@)rHZbX~&kD4*-8I+*DoO-`S~&2yBDVVxvDdmnOzPyh5nNhvmVt-jSFPa4%hDyN`(4W~r zJOF-WQBvl99%w}ViNH6ED=>%fA{c6*3wnk|o*oCi= zibILXL~x@E?gh%^K~M7lYL6BBKflo>xz(o$!WbhrCO^Xw8g_8-n7I~n7|q*-rauzw z;wlNR8%3q^f)^Gn8K^2eJR0EcX9NQG?=O^-d(hFUvv2NH9Wxxe|KO7{<OIYpCzCwa)>Fm9+ z)b6L8oGJ^)6D~AVnUZNJ2-HOO2{NQ-5j-5A!9fU^+_;;#fbBG|?Z-~aY7GvAMsPBM z-xUtu(Q< zf|;l=fj&zIo0~TsaLcD zzwaT0PR3r?e6|+4^^5(KhrB0qLQQ&MF=H|=-pCJ)_u_Q=uVa9oEbi9p{wsI^p8%vq zQg1yT=85jWB=z9-9mGdGTHaMM*IP-woWlA9577jAYCoz5gDogWuPx_{EUm~q z{I?Z~D$CapbmofCM*L1;3Fu;nmqa86L*4slgC{g33x^0%lT)e;zRg{^v*$8JqgD4QC_vl&oJf;&mg;N{p%;<_d6m zg95N$*ih60{ z?;@?Z;HOY|>=6I)hpJp?0d5e=)Wp}__4S|JSP(4236W60Sd)BbLij%oXZHQ#dsBmB zM_uJoV!%I#peai{=^(0=4}qZVEkHqotUIemA9ut`2q;F3I-epIs|aS>O4590P!NB_ zm%KW{7Shtwk!{VJWVOfY7G|$o5!zk^UWH!o3O^+b7uZ)87z&O$?~QEs-xHwgLH;fu z@dac6_IdJzI#isF|E-Y2J#9^Ob&a*5%-E=?`&d}PadDkrDSp1X>HFGhYg0oHpYrg- z!_z`}cAe)o`Fc4fh_g)+sg9n49Mkua3?I*Xl~Jz=q0<&9mF?|3sXGq~rE2GM!{YYec^s*%3?-)h> zC&IXJgHMsdSKoq9{_%3V0TYR=U3Dyd?nr%6Z%Zvu8=N8>{!FFNxhyZ1%?$ZPoLDaj z-y^ZxTkM2>r$@o}^)8sV;xTFjN{I5f9;ye$^H!uaxo+2|wJRG9=he6_b$JJ+T%NBX z9pxOOLo-}l_K$t_pBJ!}fGypGD9tJa&JgoE($Ji)#FVUow={FRVA9_C0kA3$&uW~W zt@)GZEZ^MX55G{aXdn7g^s*?bhRFG9Fi+3fP3J>p4FU0_=SEz6-c=(Tuw4pnMI4>g z8_uK0iU~zOciZN=>2=X4fBL0q2DoIia38Z|E4^gf^W-1-eYc}^XD~I?fAnvu$*Q*9 zu5zh9hOyR`lx!S9%VOOr)%Y&GvHC&h@wdYDNU=gIX}Sp0l7KHa9SZs-bVB*oX$dWU zy0h%HNEbez+AMshOf{-n>wYwtT2@skFA)_v9?RT)#h^AEm1mBdvD!=gmNi)Dyg~dF zcjQws`;Tj(w++T*CuWO;+l{IYxQDV&VjHPxr}xpTcFIhMxm>Kwy4KgqMuR;Ig%$&x z6?r43nJ;3WuaA(8F1m2~apHZ@Yx%=y?N9{Ui}te*H+uGoHxgU& zGC8%dJAM#b?31SZb0MK^R+c%FB$nq}oWHhKo;Gow$sk_-1I?3Tp;(>Z&4hlPILe23 zR7zu7N@aq0qXpSH#vcw_6P4F?kMsn`TJ_W_yeqInb^9+h3wNZl+r1M06ydk4yhlA- zbI-9d96g@pTkpPVB{04!jxgnFYdU%tdRjEk%66tTIzVMv_-SH-J=X3rB1a%k%;AD2 zr<~nb&D&C$H`l1(7>|y6K`MHWz2(8l75axQJ9l|rzX5;F7CS5PvDo(>;syNaZCoDd zI|O#v^q11?N^OyyYP4!DU1#}Y2FeWNu~g5ar8GN+NFp|(-RO1aHcUqILv>rv#ym{w zZw)0=s&NUiO$|lRU;4brCtXw5J&_*DxOrxG@8NCB1EiIq_69Oo41vhMc($hWw!We_ ziRB}T5hNDscbnPD59h1N?Ch_|XBZr}h0{W|f=N%}3=rWfNg&|Bgq;zRdM{`SU6)3_@U3s_9*SKaZ%~cSoR}!+vzby8 zPIx(%|BO$lSuKc3w$5VO@I&|3-C?*$ClMOnY?oVXQXK7)&yjt^ZRhzSvxz4BJ?8tj zaoUH@Zu+C*x?|(5s&ZEa7m6a??8HCI^zojt{8Gd9nfBKsIX^cd4(ImUJEw5g4>Vb= z^f0-SF?lUAN}Qs5yYqeI*3b3FrE6hyZ_Mtu4H1QGL{KV@p6!j~ojZ$8xsnkI?%2n* z74A%C6l5Ri%o#fC*HTms>PS8)Lg>L!-3POHKkb_CB=$l=;IA05XocTtS-A0e1lD^N zw6732v$L}W%Jh(XGtcAumU3&KK5Ae?cU@bejK(mP zD<$k!Qwccz`h|0;IgEkZ38V2W>%VTQq<8E#D2az+YP!7WE_%)O!P6vB_|2!Cp!Yf_ znbnFf+Pgn<;*qOxd*-p_O*r%N@yDm{4+;NXT_hn!tk)hkjSb#i24jB~lkI)u3?E;WcS7l6$E%(~vK1rJ^9k zpK5e-bZdr4^JeNN3Y|K`mqnr?(K{rb-*&{^sw3%{gE>)so#YomyJtQ#kEeu`yGFR`kNU+e~?YEXFo zq&zYHj?W7c#x;y&r~7Af4^l&yc<@Rm&Ro4RH(Ao`t){hM zlJdR0>&A_Nv5K3|r0u$5M-9rOJWM_gxjFC=4rxY+oAc1DeT@}-kyH~Lo>DDrHr;k~ zi{hYI@PYiJD8(y62XokGX1#HNFnnU<^5O!=o$;~34Rocgk%BovFATz?`rCDMs(%9R zf-&E2f+BxsY!x7kfEyXNFLnxg-viy1$7esf4anZX79KY5`3v6N`#qzLy2slyu*N0u z49~}27+-NF*uI@Bt|c(+^~oN}l9Uk>d0D$0cI_RPFGy6s%GFX2KHV5v_aXxiFbZE z)U5I?h4~YqwnyqUWL5X6o!?g6LqpTymZ@EJ{4nTt_=G>pj)9VPLzhIm1(5!Ku>dX> z5-0t9+>xtWRN*U}Qg4VP9uf<0LsCtz4#^gOOWIyl-xeRaNAm z9FQcmY#Nju9A{$$u@ z^}?JptL_UA9a6fPT@~IO&X!8{cjmTw3)kL83a=kCnwVgY9@97L1o$jfGp^+(YiJzq zIgGAylo7Yaunp7gC*4&1`f87KL#LOeecBsazbvN}qjvL|peE(bKgDWIHldSKZ!*~* z2t}(Da^Hye|7PkuiYS2tspj)~pufWI*Wf}z7Bg-J!V@~#p`}}jCFSg~%->F&YhzCK z(GRzy*DY9cFO5jt2DEVH5^7tCn|>znf3v-%QGl(+8cd||%s;7lZi>*Q9 zVHOsax?>k7XyE(1Mvg>Zg$(bDcJ( zN_dEO$4^Fg!_=_LP(n91q*cU!BxtM1ys3q`XXGi{rT(bK!TelZCke?(R1No$B72+D zu`|21eS~g(nAy_&bp2MhM&XX~R;$^?(aL=lcDyj_4bFBxtwW>W6T*>VQj>o6oCWW~ zawXYgA(gsrbwpf5Yu8lBWIu>m=T{@e4?|_Jm@&06TkWLTww_N^z=I0 zsq<*1!6?>r3)${fZJ6!mOVWe#gtw}HvKJE9v9uYdoCCiL-q z#5W(>qGfg?Gw1cCe?l@U`l{;Z`OZW$v@B=PJKb!iSKB>0wj{^@Sh9O~m~Oy9B~sBp z4h#j=)2FE!Ydx(W0rV3P_yq#Dy?IyEB{05TXp-p6)X?;EXHWP3r!CdRw;4sKEKe{g z43V%7lY3iyf2^xwF>^L4`)YNm_5H)}P-6m_J*u4nLCcSL5~6N{ik@U7m@4|6o>fT} z_Q8!Mr#n`m^s%wc`|=JVlNUksQ&0UfbSW|lCO)gpY%mb+y;3yQ_^xvV(WXiTsHfCC zn#N`Y#TB7k`q}535^qifWcsdMZHuY1lfFiSJ>)ryF!B#X zeY8ZwhYv&719DLY#3dyaIQeL3{8oJA)&YCOCQgWrB?O?IPN4Z#;r>aL`$(T@Ax2`W z%k@pJA2s`uqcZQX0wg)p3&8ds~r zOL{&y@|8Jv52540mTW#vIRfKD=vAM&g zXSxQBG60E1Yi=$Ok@5NE=xyDgf@{wtF;sn zDtQ=uQdt&PvNj3y`^dEPYO*H2#OXiv@N6FUOX#7l!$Rxp)5Lhpv3!1Ft(dI@&L<~x zLDPm_0Fd9lsc2`gtFJ6tO%kLGAfY=qGl*VlNUD{|nn1jWEsZOkGnAPD!~QTB6mJJdG{LZZrTk zT;mW&pnbAp4dI|b;Z>VY^Fe?z;L4-p( z3abUR5+m0ojPRmRVo+x(x|z!8dU-0QH+Ld<*OaYpvD7U#MCv?3p_l zl@8tAOk59OM_@f)AC-5%LYRf0=nlc^qP1_{<8`(RB6v~x+BZZYaW-p@cJX4q^`TiQ ztj2kyJO*+9eo*em#u2pJ1TUeuyvbs9-`MQJ{E0U#hTey8Utk{$Wy+W7b*i2u{rqxm z7WB@oRFo9FOI|#@ya4eMFC1mOe0I(4Q~{Sl9zldsYJ>oYT!SCrGvR-A3e<41kxDs?v<)JBjs zvXGoPwVVS2VfpX_nt|QcR1Gl6a8swIzHY1yH{{(_93AKG@eg~yD}m2S(Zy;3s}Gl6 zHT;?E@5xDW`VER?GtRgezBq0Rr(2VpIO) z`uz6qF9iRF-JyPkJM8yKNEpK*MBCbXt=6MeRbaekQ#0k4ZXFOis;XnYE>bb9kWj^d z^h^14H{#c-%1@K$fYc($&v-BD)$SzLmoMjhplnv#)3348LTPwE55=SA>9`px%s;eWqFOiZ_ z@$+&jSAGQ$RsBvDYsuUD`}%fg>i`?YuuXJP2EUc|%D_T~*}90h4OnQm2|;SMN<{}| z#ZTP0zd~*`iXCo+Byg#78286uiw1~T%QB8>G2h<90p{|ZPoiF@iu<1*Rd-yarM{1j zjt&l%S5m?rC*?t*P$i%C1$#kD^YFnV6Z$kjoD=2ZiVrFQ#Wq$JoVj@VKuC`>gB+Xh zWZbuRA;ws%wa(!KvZiVuT4^R6WQUlA_`dvZ>gWgjAxNjO{|>GA*JdUx5(Id9t;HjN zBIJ7XrTg&C@zd;7$Nfs(*BISc)>%xZHbDViVUJ0`(Ki}id%NBd;AuxsvYT&Dx@R&b zsz$13s~D$wFA#&Ye$LR08SEi?4b8TFbEOID;)BY27nly2G!V_*%_4e41lUhOA0(Zq zF^952)`f^!zXNuXzU)H^HD;7S$bi9+K$E{7duDl9%p*wWg9Ku{SxL-5=cviEFx^HKTLx)9MO;EIWf)&fd-|7@E4BFPSB zAZ2U-bYy3ThJw)m6AEw58d1HGTPoSfYUK`BQD`5F&TnW$EAaMLDhhLfRsAPn&mWZg6b#3s*jZJR zVBkYcvV0~-KMN--uszzpdd2$ioX;B+y=`g$lfK211Afu1$II&F+pHWtO8t<3#Jh=H z=5hb;;0#6&_m2c^J%+MF!ybWCMEypY*N}IqszLqDXp!q}CT8Y`236>i)Bg=l-LHD| zEhV@*ya>CQN-a&{rYxhu%QPk6c-|BDff^``(UFn$fsY{Wx4jr0q-^t|5Ma>EbV_-B z2>-gwoQnmPoL>s9f|R7_cDasgYCdRl%k+tsu(<24+fEB1ID-Rc^QpLfW*=Ixx%$O2 ze+0`om@$f$1hx9Afdl5GZREp@%FB>&uh7beIXdp5i7rv2Y7{rWH%^!)4aWB#3!S3` z;!+=PXH)tK7r!3Y*481qw=iAieg~}ei#}9ggjo&BN^M+y>fCntr0m0M^q-?;MX7PEMm(1=Hr~UXYpQ$uHW-TvR5~APKfdaR0*L=`M z%qQ+M2_z~?y!5o7hH%8GrYdwHvJzBS5je*M8T<5;fn*?FSW6&KW#?`1%oa{0Q?5;Dk?x8LmWK*U*u`2ARa?h6l8U4 z6dKjNKya7vJLSjX+SHE{uI`dkgR)n12@Q0F=jK+AM31qz3 z@Sm|p5Z`*P`8B|s>)9l;DL&_EtQ4y?HKXUr68&S}e?eI9r2U-t&JGpOgTV_5lHH5S zbpG??bm{Vo&`^KCCLK0K-b(G6ToRz&ZD5!>2i6Le^r-p>Fg~l*eFS+QU+bj!ZGP?+ zs@W);$sP4R7+H8#R7oe5CP;t60*a*ZIaCjPX!59-7sug?=4`idW4wLXZz9nP4FIrF zD?ST+wgr8MSFD%AM+8x1+6v8wl;%X|gmPyl$2>YUZtDB_G)w&N(N=tJu##@sy%zs% zAGdz++V-t%Z!b6ange;N>h?=HosN;H&8qC7+C#$C1l~Rb&7~9Ah8(1xU%}tOEiFNJ z2`d9IG~3?ZPS463?pzQe+Nj$kOne?u`>i;N81)v5`;N~FM{C*J>jV7<&>D4IXbCe> zk&gMj5pxM?m*3AoTU>uk<_jPPN>85%T2;Wl30c|LSgO@IXid$V;-KY?@B2 z&apATfOK*EX?V6;4<-AnFXzL{?GG)1_J$G>t#A3#C-QU}0@Q`Bl@x9>jnfY3*ZQAs4S)z03A%+)gpV=dYq8Cn7 ze(ndkaIu!-URg4-RfFr3lg6ENT4DRSX1l!==6)rmCBM@jyW=PhA1ieg@3_?Pq)||q z<^gOyQBh)Z^A4afmds^d>$3iEf4>$!oM{F~K+fP1*q z=wJe%l#&mCPXRcdfW+7bc!}PJl(MpkH{QH=h{L!%_Ay$^SM?8$B1=C1P9}g zyY;-x$jb3H!Ot#*UZ+i=yS<5j}QU z`vypmHl^TtcpDpgcdmgMq%wNtpz~G;I0Zkz`r2bv+;CX>`Fxh*j9N8E{9G5T=*YLh z*+i1mtYm1t*Rgx;Gy|MPlY1Pc?lKX#NvxDml9-g<#`~8R3&Jmot@sU(M#wxm$6Z$7 z>vx@gl(GY(cruTcK*4#fV}Z$Croid_A}0a zY1HJTtfZ*uu-ra0J>3Kl%7qEwaT0q^4CJ->;A#uH$v`jm%uGs8k3!no&d%lOzNImX zxVX>dxjVT!lw@pntwi;y6h%hsx+Sf5Lg_AT4fD!Wchsi;W%tKV;|?hrG|I6bV;p%K z|E_0B?68PfMS4qoS4ifB%#n_OV*JA0dReNy&`3cSIMSFR?{&S%`k#GC*iKU1F9Xfe zEXJ6GE#Cs6meL=m4LL^DY|Eu2ixyih*oF zH8($=8z@SJ*PlVrcjy}HpLQ5KKYoyqk$v+2=K*TiK2KC$NB&e&4>FcG|ON^8@^Om?fO^sB^i}@v0#~o?>@!)s{JL0^hdoFVnWlyd(e&%wU8syv+ zYM_h}D-`#eR{Y^G-r`SkD(hO5Gcm zpvvVjrB0k$LHy|^ncD@f$f{2`#6PtH=pS&zKn2nW(4Igh4vg?lrYdo;<>unOeC(UPXY_1ILCqfRO+=L`q5uLdx3xxtWDklR}hZVcD&Rjeg)1?sc z52~rR9Psh)ekK(%r>VbM$4Qli#*2o+#3y8~spkSiDa?yP{IB-MpS64=OGVCO{A8J- z6U^@zhq{F-MLr&CT!BJgpWAO_I^h`RD9WI*s-&l{{AB>d56l%d0Fl+E8gOjPI^IYE zf9=}9nY|FZmq{Co>&3T+-X?7mfeid` zHpx$Hl2%@Zj0^$yLQ?+?$=Nap6pR=r+QC?DnkjECadk|eD3O3p?tLc6BQ9?IdJR}d z3fmIs4kUw&bUatSAAQ))%~`?W^p9%z#Egy|wx4E8%>tKVz-s3)yBG|@`Ug-eLC1wV zWZ^7;%L(it2|`|9TKzr-wfJKAn$^e~uPD0Vj~iEqzdvR6h-f|>vaCK|Pq{v25p`x{ zO?yKPY`sf!DtSYBGLwH6QqB;i;UdY?Y`zp^l|M6H3S>&a#IO{7IQ2m}B`34-J`&F) z&g&;@T`8v%g}~8G=zXJj;0*3!P*_ycJ`{#X5p!jO-X4ep z=ps-xh|JKbrLuv;H#0I8Dk{{m{kDwLy}t;`vKD>Xp`vE+^Sc0IB-DYSqPe2}bEpI+6LIMkFG=xFLDKGY_!kP5s=)WVqL816&3Q$u#7K3AA5{As z9IY?HxFrIyU0<_@DY6T!JX@*9gCJ#eE7b}@tCK^`3!9TFKFHGPlJn6BtqKS0n<*Lh zSemMdzzBxCVpbF~wp9uLVZ1TwUm+>`DM0~8pp43PB!?2rbZejS!BBBz zyMCfwP?a-{c(1Hh^;b^MK(mJv(>4~Z!tW!8sT?w{tzIwXEhq&MBq@|Pn?>pTXUCBq zF_!jyUs?{sq+Hg)q-5GTn)Oe@?ktw&pvy6x8Pyetx#WLfFpPVU&+3Y zAHV)Jx01!+E+BWhlw~g(@L7_XhePZhP?#cNl{7-*)d)n4H6VZV{7CLe_7E;69OM{Sw~#NMlT$MD-PEw2H!fLeWBPt>_cfcb8vwF>Pq_A3rq^rp1Fhv>DalckE{f>FW?!h_vji?5Hx=GQOdwf zYDY|N>Q(rsXDUKa?Nw_YgDNsP+h_gvbohd{UzIJS+Kl&N#|qRE#k(85e|KbbX5Ou; zbCNRMb^F2JP8u}+Qh|%k8~N>+I_Mbh>R=Cf4MsL(m-yE{j1UkC6Uo8Bh_^1J;1IOI zt}uTVIAi==f#wcP?HG3Dz(5{6?8wOb$+Md~B8&)~$S0D%WJY1q)aypYC4Hc&m-RyA zL>hlAwix0HgDE}9)2mXC^Oj~Hh*J1qzCF+d<+$sRm0K<>cZA@U_Sfg_iW-Nnet1X} zQG4|S0Y-*@lhKL=(aIh^Wenb69-e|_Oce^`rprNJT3Q#uWy5$JAf!cObMi7T+tmGk zYupzv=Ty2i3cbtbpEM94;Cem&;s^~CK{kldh|c>!QaV|DUGa|SoKzY(QjrH?-om3! zP-#d4tv9O2u%hnE)3K=$+8`a<*TKJPR79dujXclo3pPgNvSuut&{yFpG?Wr}OuAW# z6Foz7RDQhQCSo_3lM2zuO(hZ#S``f!$@$#15@?eZFc(6OQyOHxK^whq#20i29sAalVws=B^!T*gnJDMj)!oj7v1He~J*#sG!y5#oasUFEC7 z$p;Z&_l=^zQ+QNJEXrZ34F69yRKaQd)HCuHlPz(HTO{3_@ z&~P(pCd(cZQo($Wp0B6FIo@0!_7~~zK=lcR+#E@Ubf2zfk{((oa_Qa?6aF(8^@(j& zU$JbPJWk=i??a8jb%X+xZfbPmH#-GU(Dxm$QX&}E<<|c->b`tk9-RW02B0Ut!dJ#+ zQ+?|`Bt&9pLN{7qR#Z}=8yhY$Ii4^Il|Qc#Vj+J8Iu-tN#jQxO_Fdt31QBtGAZ>qv zRp@RGrx4VFU`R;lJ?vKmpT#E`1lz|cM5oNHvxa>mSeVsVk3Z?)ITbw`{#~fu0WmaNJ_xhDiRD$u#O_Q(-iFt+cHkS zycYe?pg8ly3Gs>wMI#QC+IIShN=JramJ7P5*Orxp>hKGPpC^Q0EVL$~cxxOgiw$V-oX`yyic+6qaS-h$EbI1P;#IrDOiILz5b)`UHUZNo$qT4WB;SiWo}wbzhTuo~UABRrjnM*R!7**@fV^d_@z`akHD;@0vq2%vzrS zMTM51)CLCAf>r}XMeW=!v!GEaiOV3%hMkMcZvUquKuE^;H9^adq@*O63w0*v97ecM zaFU>GRdQik8YZ4W`#|%l1e0QqlDN7^^`Jv3uQVi#Wb?beZd-jxJ!HO6-upsvM0=49 zRfo48;9b_-*MGt9a{m0q&?&lc-GX&MDu2}v9Z#A zr+9Y1Q1t2R?Nxk(s}NTk83`r)4U$1C<2leIDC#hmlA3B% zrdt|A|9H9C7YP`d+-Y^%S1mDTftMEbFbk@|AYOJ>z7&z-qi_idQD`7%f-3yO=i z#DuoK#W4fbJWEgxVBO$TRK5KOd&mi z3H_ftI~t{)y1Kf6fO&qr&EZx=RsxWY|3Mw#2+@DyM^m4`*@x>lWp1h8J^v8F7_M&| zr0-p?n=a@a>iEn!f+0imwoR>c{k)YD&|aY!v9l6N>{9hYO)K(jO;T+k=-nJ@MB_J02!?u**qPR_`vaNO9Qt_DrKi{0I; zyNh3dOYE^BP~60k1>N0eO;?3Vd+&pBo3u;${a?3oZVySTpY95JEvdEWri~DCy9ldy z4Frfd9>8$nU&2qel}@{+ut}MI0&mgZVQokY&wa@y!`LFh zS^wr2^`%(RVcBU_%G`mMDd`xzGhH2w!3p2mWoK?O2#qp;X) zZ#iTn;?5DJaW1ERpjqDtQGY*$RByr_MSR-~CsT=os<`od6sS+c#xL-7>2+1JUfODf zVU#_bbWM9>N6O*@>r>5+Zo{J}mqTAmY9JO47#bE979T&7nKat_@1(gLZh}As0vKRy z2Nf5?Wn^UD%h|0L6tGAGoey7Mw#b@lVf&dH0I89MgMMAlqj^g?xrs)*|7GwtvY_?} z3R8Ib&HLfuDi|2O%}XT!C)QPW6O}7Ez%wb)`^JEaG&U-m;Ye#bm`rA+u!!B7$$Iwi znXsF&C#eQWWY!4M3W5mRWv}5?OF0kEg#*HJd0FX`EB%ue7Mq~yCuaE$`Gq6e6!LH7 z(fJys@#rQJP|lL-ku)L zlAJG8niI_aB{C;N*w}ywaK4J+a4+86G(Y(gmC!eWw++MLxj> zB-GQl1y=>C*La`tj+wnU%~SAq^2ivkw$c^SIa0>jv0Dqr(gGj^{U_n@KV(Y9o9DO7 zoks&qPffIf0%%6knI~<@m$$pjmHbzBSRs%#XrHGr9FZd6x}grk1MB^8j}rCc#|KbI z2zV0bW^8N>Kp?Gkfruz+_mVp>OzGB zl+c&JGlhja^&+}OBMO|{Pl0H`T--@(ZnF%a66HnS+J_^ZoyS(A{4fArA7Jy|_6v^W|k%LKtBaQ)`anAC?Sh>|PB|5Rl_Q}Y6(7mWf!P~%{e zZhgxb@A?ce5zh^-jGC|qCIqrEg&`UePVcllBK5gQ;pkgDC}|pEqLasG9~6&nITV74 za)eRVa|(?=gi+dV>sE#B*9q1Q=et|HAh($4#>TFhqW^yFk*>$i+7;H-=Wq(XBN7{3 zaFvloPc(-F{|g;sT^d0eO)Y2r13D`r!aV%ysA4_ir}rzlgxn};-`=MW7k@qVGPKJh z&i*KD1VK9n#}7i^sqt=9gvtyJ;Yb1+At$bnc$4(+enuFQ7SaiW(|~mqzBrYxyiFL6 zjZ%whvqg2lEDP$NWZyOvK6!ExfI?3u@F98-ofe#MBwOj*LMx>D53^joiYk;*iVEg) zGv-(AhYpZ!D-6PnJB9kA4a{*y6z(<#9oB`FOEOR9_rn; ze1$}~q{~qm+KkrK&{rux7CB|1&bhNx@aT>v&sX03Y2U8FgE^ycZ3f!l`vH8Ev#T;pUs}ivW zQhi6yd+JDyq=)ZD`rhZJTE|<9y-a&zXQmQIVu;m&U^RrU297Maz>5TZV3c!zQd1@T z8}Hp@<+Nz+slYr#Gv#}T2^yg~L=jTG)Y2N3k;(m+CCxHHqU8xTHqN(do>)UDYh85{ z&Bn00sU2JmYybqKztScETVJr=5CR%%2EgJsaSCxEneRXW0Of|ln5&4lj%kVXK8*45 zj(zaKdVAoP_Jdl7n#N<{a}OG@w~MUN8wqU26asWAk9=DQ3REIsLi))_#AmPyG(E_O z@>g?gqs9ok`xO-(@DS(&=8Z#{rk3gxUDA=-@qtjYa_s zGXX#`5wevb0N@!VC%hp9XBeynB*ki|&lzWr;7P$B- zGuPh+t;IKfQ1viQ03qms6-7@%n_y^7l*{k1^IQGyL*s6j7CxS**hMVgs(W!pQyMKum%F z)Jwv#*DzSMqJV0Z^!99Yu#tCw$GM2w_ZJX|xL`U+iq*iw%Aii;3>zV%&{2OIdta19 z1?xSPlXsf;Em!SI2AV?5w0^v1+X6IdQUvdYLRQh8uYPPV z4T`g6nsmwFFMrd}Hil_pc3NBd1phMS6E)-qjnjw*)c2!WqPhBn6j=+caV&-XWRcW8 z$_%M|^u$p(VB-H@tvs2ryZZmI06;DRlmD;}wJsG|je3URs*$&j9$->o-;j$U%aBq< z*)KgB=~IzlP0S?%(0UDl*s)JR<|Zc_z}5Bs{VW0n#sc!YX{7oXkR&zRylppOJS7|@ z<9x9mBy5STh5sv)&GSVpRP+dY!mKp3aIW67F%31VJ_avUEJjb+ht!+_2~6^U5-X=c zm7lF`M0&c(^XC_!B5T&_^|do&-+fwkyb2RSZiHOK5xadJJRD%JVJcT{9*_Gs_`=vU z&uh}`M@%Tf{-3@+jnJQo%=(w>7>49mP|5v*5N*QPlUn+U7%nrG@+dU)X+xfXFC(kj0Pu(iczN z#D>Q;`DmD9iDh(vSXV*>9?CaOSYE#|7|=8Rf+i%oS%Eq)6~2p5r|p$>!>RnVV#qG#6K75aieAM2SnL zhrIt-LAjO~mL$tH(ODuaP)?m@^o)$B*o|<+ZZZ;a=fksLF@BE^taCpQ_O5UkHX6PF zFYp7RpW9gH8$)#9dXG;?SXUQcxCzv}zJLF|Pyh-bAobqt3dIL16~OQrHC-(|1WZ82 z>)?D5S<|2r>Asx=s&?b{3m1So2b5`AKpAh?^zp$#0qFDl0jw2fIQaQNJ(nH`2mL)h zb{H$b#d`T)LAvBom`nCksl?(0hjZDjFpA7pHSv}J?JAp`_~guP*OSPW1yS+Rv5r2o>aj;UyCmyUQiY-H5eErEj?#77ivbWJ=$Cla3-;H! z5o&s`M%f&WqmGQ?gbV%)bJ!&2_$akx-i`Hj5pdH488mptt$t?*K)c_jRe{L{G&wG{ zePL#1-dX`!4#@udO;Rjdi93I-#60OrdtG45kP--H3SPJ{QgcXVa`-KM8F9G zEafao-z-qZnyJkP*HR*)zvL=|@GpL6WTNU@uAz7o!1iri0!S8VsH!F;_Z>IOf+TgT z3FO|lkzk#{@_%{vt{;$&nVB42z6;~5X!S+-EO@6te0a3i;IjfD@t=cMj)a;)xf zV2`U(Pd3yXX5`48N6r7hd2@yfw%uJ4j4W1qzu)>WDh9p#RGdgI@e) zSt4?F<}^VB`&#qWTAdNz`REEImJaxkl&)dqs-i3!kyTyL_l&@Fi1mk+qrN(2OEfm* zWvTVoSLcy@r313eRi*$?w2UkJohg55sb)36OAI-(>fLnsTA5I`1Mi-w%ql!rzZ>CQ z{NLWo`S=af8gSh~Z~N)Le}nxJ0a>psnR8FYq@-dnQGtPwvjPA-0jXM0fSnr}a$g_l z0Bi@pojE;+H0ZcCI+u*SUs%X%-mcs6#vl7__>hmch*;Wz)$U5e1a(9fU!jC=!hYA} zR8ZJn5&NjjZT9MaTj3|;*#@43pSkRKqfa~_8$ELKy(#NfufA4v)l(pSB1kzm^=;#= z?fhuseqCYZaAm+0<0w-frwJFFV<;UE+4ukc1>_t69)WC5bSUHFM+;Dh+}cu!Oyz}sZy_d?DkB>wv+fhRm>O2M98qVyK73) zTtrIM$AN(Mp}+&WTQ{$TZFn^?3eel#QOMWdKIAqwiin9d1ErOPI=HB)&2oDiP}~{F zewChf?lL&VV{^s}?t#OMn3|YrmG4gAw`f zsA^2J)@uu=%zYtGQ;Y36h}_I;iQwg@BnUxZR-{h^zGh>Y^nNRV){-N%Ss^`*yaO)X z;R02)pyrFtIs3SP)D4jJ#7h7t2A(Ep`cTo(NPOsL3|s&=*VYscp_L#B*6GXyWVB9a zQ#+`W0b5CrZsR59YH)060|vUBqDxH5VANFkyXoM?)d6pL{%yeBW^11_DWw z(;^KSR(Fj?nqZeEI&@A6WIie|gx(`EsVOsiLgYioA3{3UxLXRNnnBq>>?eP1o`tomgmQu6 z#;7)79kU;##!I`>#VT3{5jD{YOqowds%UB&k8VnFfzp6vZ}@bX@?mh1MX57{|L(UO zjr?b*mlk7r@z#fh;v!?@Y^k2eTM%)b>w+nGgb}B>r${i0W~=V|P2yk{zQ-2wK%bMw z{#uWcyi-nfe~Q7)qO4+*u-+e=U({{XqB&ERYdM}jAi?{H6k*Dh)}4t zHPmmxG4S7%EBZ{IR)i6F7WYe_uq1p#$rkx)RiOKSxd}fxrZqn=USu2rW|nl`4NZKBcp69EEZ%3`I~V z{1=@tZxVp6nj?ZV3P(H#C6G?6Qm5HWZWz59%1fk1QX2zli=Q?S#kt#7+Ga3;fV{!X zRBvT85CF~_r<-i%#Ru7Rv#)rmmdB5h(i8^wC#a1FUqQr#-)FWnrZl`7is(ss?D|0} zoeupnKA=YDkPvKAd7vx;s&Xu&8=X0Q$cL0jcNGmq$e)29&(*3ix&Mj0ZXJ4M4@gw0 zDHKKMvrX|uq7(G>6 zQICIO0wG=0t>GtC8bSE{ZwoWt2nYum!NFJ5fY#f%#WWj&q0#lCP()eRvmHy!r7>7| z5CvxoH$N{l;^S>DgrM~oHH7bUs<#uJ%grVYK^xaXLf#R~{Z2XL!NVV~8mgm=F0PEd zpNi?ERW}zLnA07_s3C$c{#&eW`MX6p8tDKtz(}=(@YL45^k^ibqr-l|Z)0|U@O$FM zngE2KryQJ%+@8=)-du{(h}_iEcrn`uqNu~J+aepQB z{Y~j545MCw>2*!~43iJ`(l@E^&NVL^y~ir$(vB zkjt!A1wY^y@Bib7-}(GOFw7z*x7P>dMv#AO4B}CwUg)sP7}Nc9aEQPDZyiIG`oX}N z^pj+vg`g(+`QyS{fqIT~IW7V2DA>1rjEcmp{mjCGH{fSdCq?}L3IXmSuWt7ImLaI_ zD=d?z8G$0-Xn7{|z#77p8}JHl^fKG(1}6j96Y0%fi~rP4kQV-hQ>bo%IxXL+>iKEQ z{WzgOYMO*mBkNA~U#QgF6<4X7Noe07GZPhnQ;`ISLPkCWJaC!E@I;XQykT%6Z$YVz*N5=xxzg zUHIkNg|>;$96#%Zf8?PRaG7IureoN{~*oQvu1=wwBlM5mKN$-2iwv3Q5mbP(m+RqF<)8d_pFVxE!3OP+ z9y}&@49YT+lj+_ZIS<(iqm|7p_Z+L%O#hvTR4pTCzuS!Nb$I*wHrb7;PPG^@HT$0s zX$&9`_k>>=Zhb5)$xzt~sImDsRq^{bM%%glOv}2~ge5JFcC*W3T7%jx@_>WiTeJ9^ zj>~Q3xx+%hh_%YUyiu0oAy8(Nj_|3sTV6_-(8Y$laHy!3wvLHNzw445{d1n?_BKz) zX~VDfSUn|(#184s>TNe^!j12@NWnM11^U8d81+8-A!r;B5&qspM#t~>ub*=*-jSyv zA%h0hw@&XIZ7)UkEl0H;U-aVB`UMsOc=$hFz$52VWahsUAnASn7iB8I|EDKar+6f@ z+^oSk`ETZDGN6a9DeJ7TRtcpV7Im5^cqOwBG*iE;6_t)ySUk;;)ENEqq5aaowe2Ki zPultP#d?G+{d|4??9(jCp~Smy)|}-mn3~9~7PvcbJ+d7o>s(!k?nx>T|2swvxew)5 z4Hq~JPED5UOM3k3$-?@Fd2!+Ez5}Y~74a12f<~%3)LVaA-IIE>!4E4D2 zt{hE1>AfP^;gvhDz(F53DKw-_fg20$zMC_p@j@>w?Q}Xk7A<=3v1K$H>g%|@5bBhJY`w6r>45l@?h0ecPd zjfca}m~w7iRvDBNoh zeYP+^SnfCLk~aP_qQGXjj%q~bT%GvP<&a~M$k)GG&fUG;g07tEUd$0f@kfn9jz@Dd68OaD~3F z?Lu$Zcu!{p6nm$pM8N$~itRCbI%RU}Q*GU;v#xcu(UGjFYEyQh&#L)8gd819Z2=5e zkQ$hNHi*U0;8Elx=r_ZTxo}>YIlEOKW z9zIlE$E~lg#(H}SSpGhYO?qWzB_=LD)*Z2qwI}&`zdR<%+*&RxW4#GGX6+t@vWq?*e?36vq$l4kI8o5{z4TL6 z_Fy7se9~XR8o#p-s)_4B_^_`xR1X)#XLa=}+I7%;uu$soZv*r-FE!KC-jjpcFE+^Q zM6=qj{dhSmHY-H8KJli#eT!x*;UjpnYR(DLjErONMUW_&JY0JK>9g9;h2HUZED64e zHR)E^$fmue=vLoilm1~*M@9RkT8GJ&Yah2=af=@$bad&!?}e_>abRGeXtr^0_L51A zm80fuNA+@h@Cv0J@0o z(A0zL)0GDYN+Gn*8MFWKmXBe&7iwws^8T|e0 z;q9&MZD-|U?X>qHDd{gPT0{gG(>xcY0)mb4OAG-k2a2kBlL;_$#HawPaKj%KkiH`- z)D!mt&;;*xzwh-MAkAt9g2vcbFV_kw7R$r`msbT|*Lh}t)yu+tyJwC|{^1pAC=S`z zwHI$4@}gC+HzgW<`{;`ffol()&&j{3H_P+$O&(2lzji}17nhbAwjBE#7l#8K)UofX zQ_2R0V9MRX?fv(}>0gvO2^s1|=yJ90uM>$)!p$eeHAmCqBU_H=e!)+lG;aj7`|c#O zue0r9pfb>Nv9nu~bUbkeL3T2x{&B9`QUPteAei}7nmeHJE z*m~>}yRl6eS-D&wg@trI+Jczs={0OLNGm{&9?%|%nm(3SZu63JGnoz_or=Qt$!out zX*uTFkDdjGzqkw*lGz4npmO1|bi$^<{(e-3m_=N<#dQ;wB%&=wLEZfNZbG*b%R4cvyIN~(E=M)le0{Qh+u`x46S zO$jen6Hm);olT(!|7y{W5Vg?~#?jV+t&wc!Xm9K7j?wlJdr?5}$o=`A!TGSCSen!E zEg8?z+liVS_VPZvWWS&g$>*ZJce{W#_29AA^+ZX4^tS9ctMQb-qqS}0DfW>gt=qfr zNP3S!*Q|7>jR!v(TfSEmV|xT1E$E?_u-%a|$E2Ymo+RSsEeL&)tY;X3|KQx27;9nv zoinEHo$2spfeUe$x`It!^m1{z^@BRIsC@7)3yrv#xWwTsxy=)i<};D_tS?FD1Ts#H zV0|L3k(uoB?8`hXTi>P`#EV=DpH6Svj=3i5WMiNdZ&^cps0h!Cz9E|o;B3;%3UB`m zP9=gTfv(7m!YpJ4elcKqlg6>lrHb$L3Q;QFqJZTnKq zUKh_Z@O|#+?_(xBr+h9dpN{8m;y#!Y0!k~4VR#CXK z?E*P6)}R0E0DkHm0)DDpHh9-|Y8`@dQ1@;hLjP;nL`gA?ko7YUkH3?vo{PdVe@Jn>jNs&UT)}~uotR2rjiI_iD7Yew< zkn!}m45*s_r<`T7)=vgGkIJITVemo4HM{P$TkucJ6sjdhGX%i@^|$}&iVO|4th&!2 zV9_&CI{tHq@dt_^RTH5)T+Va2cj;obG46He#Fy%)s6D2r-!v}+AWAz3c z3D$v*C5r(W?we}|Shx^>l@Wa8w61}{$+r1*GN|z=h!)n=I0M;ztrIAaA^G*|S6*Ho zr%tgF#0|IOfOVX3V?a3I5G!!L6zdu%{lM?>sn)GPsiKn#jLWt?|LgdM?0b)WgzPo5 zr7VXt#DcL2#l8N#Fq%yTVv+6pecStv01J(k{Od(sS|fat{mEtjN`JLsvi|cuL zu^DhzX*jby!g%U4b))s@&z0`O$VkoBf4h$vo%`R70IlkQgi;`P0d!4(=F%~ccgG1v zcTtGD&+P?VfAPw`jZYb-cD<#!7q&B+uPptia}0pWdIs4h0Cv?HjjJAkN@uW(ik<+{ zTDIT8Yrm{=jdYRAA73w5mc(2)c4yipF>}-miN(+6e5<=e9-9X55p-5=zgp4FaAG*7 z32ZM;Mg$Up4CMU8ZfnbP$$Jx^(kFY%Cv$eyz*T_P@G}PxeyW`ZdiDVSJ^1@Lz~0vO z&9Bnpu5X}T2L2F`+5Y@04|wGL>Cw{8lJBO&QtQ@gtTbYTp%yq;dGYJ6e%Wh>&o?>% z9|jL4r9SA01f7e=1Z~3|f^VwNnE*Yo-D2i6vcn6|?p8Z4cbvdV9roPS>?=2TcZdL0 zg4I60C9l;6=d9u^pYt@er|-V7si!!jkbpc$3@l+x+sK3UKEtAsU zaEF%JwrB#SDozlAPpPFOu6x2)!_!|YKjq-#ixgE=Q|sRJQazX)7#v)UMi#C5V-w%c z$jb8gJyYw|+TJdeaTd|yf2<;halLfX-T{hCVE=}l-^*s_;c)ggaY?%v8dCbQ?Mb3L{AOS;C5QQ8KA z+&u20K{AdtUherGie6hTf4x3p_fWG3@asDrVId)wzqs>TTU$HXo9oHfBWvH|*)`HG z*5WlmXY%E)XLZlJ=k3quCyq9C0`_~UC@2yQ?xg_zuvWc!Pi1cId#)F!wK##iRM)P1 zdwz?Z$7J6Li_}ETn?+?bC%+@_jXG=%Ly%=u*eED`7~HDZ_B{gfm17-2W!KTj+uH~S zd3JUN8v7!YyZ*+|^EeS00v#9U7vTSG{c?c@5o-)yvv)u_1{U_kX}>hR^cz1QG&HjV zgpKwi7-WI$%)H0WOufxGu!0HrH-DW-?ftv9zgRPyR|bnk>nD{WYsb|S5 zpG7$NNa!a?Ty>MCrRA!DxqpL2?*OBGSV%>y*Sb=fPPxtLz zm$L)Z&*?%DkKF|Uo3VmZ2V#sTyw^^%_w(ehr(O2oIBxRv|BAn3(n>~UGeCYA`>YY5 zj4H`Q&EK4@pAueL0RHcr?MhKVG!uK-)l);?vIFc(=A~bPSTr^^mVJHU1e(O>hsjq@ zmIL-y-Z6M@74H27Y|YlzpAFMyZQ#A2t_Fc}zaMxg)w{I{+5I0DaJuBXCkZ5U!0^I| zN1P-bwBCOMtyp}*qN4A1FJ|G{y>-RQzI&R)l1G0|+D|S4i*b5-+W&Or-{j<^1D}vZ z&wG+75RjHV_}~5^E=a63F*G~z~WTxd0gxs z?_FPZToYffNGmjH%`5WA2@;9Qe{5gT0#SXXWP|P!^&u?{9DQacCcej}jOy=@e#ciJ zUNh>Mzuo|z?p_jk=``X()p>c`nAU1xyQ$jZr};5Xd>ky{k$3j3>?4;3fJCu`}Yep_&@$LF0Z3AF1+nJ(W2fje1c|nPQrVzlJuzFcf+SYgHteDxvM z_j7vqr~^?ucJ*!4VhfW<#Bf{45dkD~8XrptvOpy0R_&}vrrO+`I%eY58Nym!{RbEkgvT4Gzg z;d#!p_dffarek#rCI?knr!dz%#USz~QzM=i}0^ zrt&{)In`NvB~7CLKua|4O|9MGa#~eIoYVI0SGRmk{2kkOCu2mtb`rc)J``GZiOIUd zq+LO8DkhccH2m@o>#|1l3BE8TsqV(LhW>h6F}d-aK!q#-^Mfn+ExRahaGfoxTu zT(MQ=cl?ou_#+qbfLux{NTaui=as^Wr_uC)zV?FuI?pS=qwxpa!`IXw-q%U0ynP58 zw}^{geF*;%!5=dih-bqD@b*=tDtc9HB%WsMyw9T3`$&fDz$gXVt)u$Te&;T-T{4Z7s8m4}PZ zEFwHCPSp|9kQ_%JI8F5U1ObGMMvgr@5pX7IPfp*FO2oa{SpfuTY`|wt9l#b6l9HIQ z!k-~wWXBtN+H;+=90#Xoj0WzjRdDaBxe_5tBfKrXOccK%G`Yjj%|kJ3jLw}qXXyGY zHugY$rh{g++H(~)xrtxmEOPH{ivl_Ldvcd7%|7y4z z%jZsi=@Z(2gW8?k%_n$oz*tBDRd_n@t373L<4~g(&(_1D#S&_afir_)2d$noS2x%pY7CEaG!imdGYF1l#JcY)~s1gxv_%mTYqV5N6Q<8$HZ(Y zOM!EzFkpnGa`snvl~p5yRPi_UX=_vO%i)e5dF0IMVExF&a@cv_A9XV+j*sUDX zEEW!X%>AZF9j^BKHtLEK#|gvV>C~yKYuEZvHLRyL?GEhiVLnwfZxFGHX;PB&FsUUR z+csPO=A$)SQtl5aiVH8pa#C@GCg>`D#;7K@`Dx_T4{ysiUg&7^<>{z7A|om&NF1av zGcYm99CXBbd=RG+$i5|IeoCXXtPEvA-QnVN0!TX#M3745*O~#5f%m?x&f+{NNj-XO$z#AFrsn##!}z{yh19 zOXC>eb7#orZ$Q_|9?YFA3iS5LzTc_9%s2;`*$=e$y{0gEQLFgx`2}g#CCfU0jvsQm zefxHd+jP2Bi&#$mS$%zsoT|dsDXjZZQW7I!c4mF7to`76mc4RWR)1CZilD1|q(DHv z@u7{IHVKd{_AFc)ad07J@GtxP;i>TFUJWbnta-qE(F>dNM)GhAe!u2sdqoP5bmg%M zoq4A>p!Hud_y<_~)u9e(&mRlL^oWB$xi=g*&4mVq_Hww@Pr)o7KvMWufW1>~z#XQUJ@ z&WO#@J45nTua~MzG|0U1y9iy!=v8s)DE;u&7;MQDvaOPLNirOAu6@^lT}DuZjzZ;Q z^2TXaTC}>-L`9dHYC|lORwk~;kGE?o%vS$nR@*jZQdlU2{jpiBY3p*|PFL;xQYI0Z znJ`9Ah0^=nBwIcrK60pSsL(R=3a-n%KJd!M1mpGSau>gP3KxlsGZytX5(3$Xj=5?a2*?H0gvS5;$qu>;Q->7nnqjvOv^&`hGbm+rP+wq~>P`xx|ZLE;*^&BZ#;eiPL`CsAURG}z@K5WSS&D@8ss9xe7d#6YA+@tqIT6z!RDXB!;wz?#M=e+2{U6dRr)itut$&JLJ`>3J2y9HWm6rmMa)UO zYPz#=d+x%5k_{tiK0qd516qe&*{ykEj8kbiI@W4EcA8rixUBj(H&n{xTZ`4yxFX0SDz4pX8R z=EX@{UHm7kJ}*m~D3cw@c4+-@Sp}n>cc+L}fL3T>0!2lIG{EY+ckghIr4&WQ4<34Y zKSMd=BK=IGFIWlGr;a3`u167p8UdO2(3R_Z`lxz`B_&Tb-}5ggso9>`UGaPsZGRyL zDNQ|$f%fD^SzS~tXBG9Cj#+Kg^=Jkot5W}}I@XQjd`qMAf*QO}!CWzJ>coj|G-^?p zAN)NqwET@>#BWj#&oV13>x-G9+UFklE#+ss{#INX(>ylH)MVlppa1Gi^bU6pzPf$9 zvy;Cy;bfx&wu_+ctK9p5Fj2R38`Dc~Is{ah84zDxQSJgVB5NH38i1zh!g67`a|vPC zCg=-03SHy`sUq=n(E3Yd)L@yJeT_Xv)4~Nl+ z@_a%<2AG-Phy;Bqcw=?$hg=v}t#rn``KiNtLwJWmmVZetFCoH9k2#MnhMIH-8f#(e!==uA@aBHzl>d zvK<=e6AQnO%5BsXoAR&7zkM ze@)e}T}QHz1rDT3-m4^~`q3Ckt_c8s?M=H+uC^7aB^aIs)RE zc6nW3BuzTuYCQXDl)`{INjbam*Pr8#ua-LPu#S{=AD3n&qJFsID8lI1DIi?Z(79)K z%!vP0MhPVeGL6!K2d-0`TOV2%vs{`^SSp*T^^K;ie7!%CY zf{^it8D|6Tg!qIW!}s9x=idL`A3XD@K7kR_V&sLdk(NtwZ{F-}j*>95u(vPsWg5tz z{(M6mU8f`JZP05JjO*2l7jm;*He8af&ON8pI+7d@m>*WDob9(ki_v`|BL2i3kZ5-@ z_A8|(XUsJ}5iu@kLN94^k6s?xlo)w~Bi0>VX#ABuQO1QPpj%e{clpv=`gaA6cTE@v zyjD%ca^JmX0O)0Mpl&2s_O`&v|Kl7h8na5?v`pUG7(wE~>C%@4jygKEzrsJ|pTxA$ zRwJGx+7`pHqvDfb(n|Bw9k+a_4YI?;S)74edQC0Q3w@e#CWWdVB(84W# zM{dTpWM+S`-O@P6F!I7W8Gs|++vBBA$*F&<3Vx^CHR{5k$+60R9Gk3{ctNe zcd7HokNX_;V#EK|0vzXuGkXiUFtnm2*TeFke`EP@>#DZHw%5rgPUx-tq&cE`{mSnS zC6*gL|J}>vKe0OJR7$jnBm1KDnE%Q}d*<+ivCQ@w@7cdUtH+2--<221Yt+v)*|~Xw zMOep|CufbTH+?(s5oPDKE(Qu_gh35`zsb4r2|fj2W{Ze2Z=2S4LM~pfEd%GJ`Ef0E z)3DC(KYwCAD{Q%ohs4FfMCjRBM1dWhVpOlaw3%r7{iWq13oOfsS1l9(O>gkIun2{6_x^<{2Rm>dc z^XOM|>&CIpPHat-87z%b_B|i;e8a?;2dJ>_z_cignc-4$3gGy6mwc zGvpGufCnf0#37c8EzyfpnR#TkO|7|H9Lyv!>$?hwPY(mqtvy9CG;1n(*^DoIxFyFd zX&*0HH+Qba<391bJcr*7gtcEcG7)IZbSU>?Npha+GX*%e1(SIYlCQe$C7QPTy5QO_ z;OLd9(z5AkHqz3{vFQy4<@s`EW2^Dmvj^<@Kf``sDEo_&d$Hl;_L&xkwo&S=i65w^ zqig;9tnI=&Nrve+F&Gx@wuLlPPDSt@yws&3=9c=RYjSp?H@|cP>uz6ZcTkD5E(B@u zBhno1bgIh9Kz8e{?++p4gA|>gX|~b4eEu>(i)&+6)|219z0x*4@AljbF7EvO!J`4_yZt3|)z#4b(lIu-s2ahbCn~%nX)Y0~DgaG#AF-sXm(WCyo2{^c=x%onw z!_pzSH=}|P5@yrk;xECS#d7G;1zu6o)>Y%(!g(sHAHIAEL$peCjr z;)f6XiXO-JOmRt?-wXY^6|*3*1O?AMf3e|>gK`2?s$v1ewHz!Ds=z^(xmOYr5un%@#cIXmy`wL4SKj~%%&;HKzM!S<_B%!rrnojO(A7s$hZ$7EEoO5 zsD|rC$``XemY1m4Zr)TM;BSbN(AA|heY`q>F)YWNdF3wmTM%Z%2B`Uz5xD z(omx&jPhI6Cyg9R)uX1D=EMHd(HU;dmKC!Ebx_<=1j1#7ck_O%Z_Z97WQWhs!jOLa zg+6AqMmw~o!!u+x@f@BM5| z>{7bGg7%+l=EQQFIaW4ii^0~gc6xt8^0O;%NkHRBrnC~prLYBdxuVSebeQ`LtC_)~;P^(peGb#a{|xxWFc#fr;~}qbf2H`^1tRJA>*X zBO{fsFD=b@yubJ@50^btmw8FrshZ0td15t-+~&7#Sfg~&p2 z!gh45Y;~Ux(bE0?<7W80>sZH2U`XtC&|Jrb=5(95Eg|d&cbfP1_5wQ>M@!XzaC1>9 z<1W_;*547M&{k2gxwzT!01`hp_2`$5+w0U~eRi~L+*HiS{(ys5+4a-s$?~7JM7m|T zd5^5@d_OmWojkN^$S6SAh8HfN+ah@fi<*q>^x1l4w_tr!4?gfxWHJ1CWNsId|J0&@ zM;o3!%l_{-x7rrG2g*}2d!Vl9@Kz_Md}W@bckkHcGp^2A)t_nJp7Oh@>RBzh*?z(K z+_@ZU@!_nYdzvv9ZaS66v}pYt>~z=VcF+FJ2wDzBf$I!Q;?Ba|oOQ=K`~?JjpxrjD$fxz2ZY0shU0rmaySlUwn0G{HvD4HQ%{Zvgc8et^M~ zCucOv*$-WzK@rHeS5qrN3gcKmLN$vNHaFk2ob%^B7R6(k%RWKhy!>qY`>FTS(^sPk zhApgZ^CL`Q;N~r1Vqq+i=00RUn1%`U9&@if-p20<(SLPA(Y{bYm%FCE{sNh-aJwtM zK-KZ1Y1t#mnU29nLI9kZ9_2XQ%)mRpl<~}{Dr=cT$dJR2|VAdt?Mw`{%!R{ zuUI?)@!Plh?=K!@Z_f4b80gN4kaw9@W|7ara*v9VN-Fgtga=a z_&fUWjdP~F8b8NtanO*z+?)ar5kFK#h*nlD1^0i|{iRb|6@d&5=QF3QU8 zs`v4Qy8_-l@5?dAw{wvd&E3CX#`cMT9XtxIj^kY=CVmcWZc_c?J>?V+JGY#v)Q>C3 zAatMqs=2O`B*VJ`B8gYWx*s@madKk*F>)U1I9v*Lvd10w`@tQGc~|<^(=2mlo#oQg zAj>4Cw(5WEx)Vm8v#_!GnYn=E0)y5-#CFS^sh)mqmPB%PMp~L95|X?wgJZ#pPr=o} zbZjv3S&{yYCGQ3@yRM_(=7;z&RbI8&PdC|}{`JlxRI@Yde+cWmTYozJ^W>@T4RL#m zGkso5U=gtyFO<1}BTk!N?HD}}gG3Q#&ExhE+6ifXjBES!mfWQ&kL*jkTubZT5kML+ z&OpOIqj91?2qq^OmIgoXtM@)Ui2U zp2}R0yOAZN>)&*^Vmr&DN@Vnx^hp^J$nd+ zvawC*bDt<>iP5N#aRt`Xwi@xpUglR$wXwARP~*~<^AEVEZ7p$TJ?0M=DQ+=D<9`Sh z_)lQG{|k-+!twmYix-SslJDNUd4oVYM1R1qjD9O@k`a;5-@g6C#Kd%KWTO-^kWIrB zw3ooV8_T+y8rT~|`#r7vkz#kDRhSU^gDc%?We#F(D+-ld)93yW>bi|IDn{$r*wP8RK76&bo8yw=drXhVp%)?tQ>AMJ$WqAA8S z&)c6xalxwN+O1ndC^S-pkT9K$fg@gk35xCuj>?xWul#1E%+Rf|opY{JbbnT%W1cxO zryQE$>VV37MROEBOyUxp~f6H1KIfy9@$~!X8CWaG?NL?YGOj&?nM=2`VWwBwe2$nW25l= z(gXBk2{24StD!)U?4@`pAjf#)_bcNqu_znsw3CE8qw#6_7_u5fP(j*HRwxTuN>^1q zy#_obA_OzgtR6Rf>J4N+`0V4y+kmYYWWpkV9sR4U4C>a+J#iyh6J?k<4(W2o{tLvR z5E0P`bd2&w0dCn#1>fOa=+8%k5Gl)6m{^vmd`k*zh9S+cqbLwS{aEf2%pcS^UwHyM zqF0Xz%r(^X>e^ZYL=hvm_yF~saC##f{=4FAE~q6W;LTx^X5k z659Fmi5Jma3%gLCO(@I0-)6r>g^9pmt>j+&f@p^`=;tlAPX@t<3i&Ar;+nGyG+v+b zTe^2Gj8((=chpr^9~b!@Rje>w-^qWH~Ps zA}g{PS4Z3VSFgK*1t};lK7q5%#EP1C0x1Buk!(euAuN?;nu=oj{IE-_$8t82Ga3E5 z8hfi538XaP<5YA4*EL>Lc5_=qqV?k^n_-B2Nk+y+rjYvPi-NeG*Pcl5TAs>vXDu&e zmi4pB!nqZ|CgvR}ArZDT`Pw1>; zIl*HpxpN4=7a%X!%wrYp;?lxe{~;WhGZk^l;8g&-%u+a`_VDI*21mheVCXgo>HOoT zk59ymx4=}*&3erKlGeQkDxEr_DEN2-QR&{bzP#<97 zrztSVrdV1o-}g^eN)C%JhjuwUIO#;ZuJ-AH4pPfQ!I&n|-&^eJfq?US!xOi9@yqZj zxJtJ|+8t-$%i@!4*QPB74y?oetz1m1`xuJ*I8Oo(F3OeWO%|BBja93z5%qTTh}{! zXhi_h@lIZ`b}JGUtR7}vTmUF z>)dOE_=r!7zIuV(6io7f2QeWcSJY0m?oKA58Ll{}DH{ zjn4gHyHnn;BkNk}&#{YX93g(Um{#s7wob!8w4E)N?m)FsE!P#x-13KQb8NEH2-8*5 zUIHCu%o%EHYeT@S7QuiYY=F6{ml0s_o7l>TV=MJyMeI>((_h+lk{$LOlKbI0+P@Ms zEeJsB4m6tIYrHhBSR~cCHg?m-jh%YsR2v{8z=DHUXsklyVfqaQM)pzK^AMm6$sCTm zg9FLAWGyXTHy0#BIIBi;+>DJ5DwyPXV;gi07?eJKY#MMs*mbUN4pk%Z6PN`T9nm;~ z5azIgg({xgT6+fTwqDQ7J9)j-KeI!x{Am69&bZSKu3OP73<8IH_v7XBAZN%TqUV_6 z#IH{t%QMSE22l(+AO{~kGFwBd=Ub-tAPVBd9Y?<120@dK%hJ)+Wvg_eCUf3mV-0~Y zv)Hej8@RGEhTj?^e{uednm=*ebVl-L`96FQiT2{+my3QO7+`>vP#}UCTgrV)`vRo# zHPp{oHhernuIm`3DkEzu3J=-7F8InOs;k|>%NR4^Ia|b`h~T?dSU3|$Bd^DTKLPya z2R}jG;oEA3@pIC0gFBcvP+*N4`z{c2Dn{-l^rb;Q<2?cbmuJVJp}mU|H?`Q)LVaN6 ze}MOlgmuRY96JhA)#pJ+z?`&^K!I9U79k<*-P7N1U6X7qT%# z&UG*Ptr_Up?;d;*CgqAI_f$rQ7CT*9@5`4j$L@gM5xLAT5d&V{3oz4#i;EBfsj8Y< z%O_KZdggK(Tq19QJIsV{d)KMa?frDM7PjO_!)bDCQM2k&2T&jN<@OcfAa%Dy|GC6X zW(yN9dNwl=FoV6^nYrnf&<9^z$Em1V`@yD}8kj%X#B#(Aw^>a<+4PTyijMv}CWd!p z$FnPG4Y?lr^~_#JjySw?r^Vq68EH=ML{iYT!(RwF@lItR2eNbxJSTXUGZo4qfm~9e zfqoBoritV^#t`Pr^(O$=`0V87JA|w>(xsT9;e_rNaXNn6c#X$?Yt~WZ4H}lb2>cDs zyhY%o_Ye}#n+ufp7-vrZ4JL6m!?Y|**j=?;Vczic=~4_{bAy`_-azBAsc>Xw;Q&dw z)ui*6?XG^8Gp-`89Hylai#Xy|5&*F-13v_%JGx_(ub&Crb!oCj!)6zAU;938*ekYl zjN>qYVfimIIR(cM;jEBoxv1T3^}R?;5*;$d%#E`gO}c+*J2^Rx1$M%eg0?q_Z{FO1 zrsA$BXIa}fwPp|lXgK*rgAF!$S|0TLk$k7TxHuKUP7RTaFsp}#q7I`Bxk)}5+v_vK zM%~@p{qysmJ42C8v24Sjl~?gBn~W0#HJ&6H=cb??;T76HfS@R2>Gb;K9sM@+_36_( zJ5HtHjA{HrF>m;IwWDAI{JMH6=ChCvja`OnxRO@65&l|%$?kZ&*#K!Jzfqp##L9|_ zv#7|qAiWzJSjfF+Jy)_XO0V8FJq3X zXzI0^pnSZ_c2ns>F^=Qdi(ns3nGTjalY4tvmSK`sFn1j<5z^v&5>MP~@N(nILbWwD z%34z_;WJ4DRFJ*fP2U{d{DX5hm<(cAHSEZSU)=4qjrg*`gT15N(ynKhQjBYOuWrasQmo6E)1k6voTXsnAsGO>-dJuw3em3jwQ-&F~ zdfGJ&$4{5RF@L2b^g#^zWh$6oXoVv8ytbs#gfi+0s>~IvpFaL=vj@r$>`GO%$z;hZ z-z)Cky^Cyl!br4&+exeCMU7)JEKPiFlSf@++~#vORyqOT@kjXej_Z0%RsGgfn(Fo6an@`*f@iM`2@!5GxSvq@>poE`1*;7EmmQB|@87qNQ*o)xX`)v%S|;)1$DQ0zzgUMiN*oasv_oj| z_uKZ-F}@tuH<;x5;WP0c8{>oDZc(b-_x;XT5_O=)8R*)GcqWFMF=#7;;XI5NUI z&N$-^^^WTAZFcp_i*ictfx|S2knla1p`^lRI4aG;$jAr>VVcz7j%3po2lLjfy)l2s zY|f$cxXu?xqSGeNQu~&F9UX%G=W^+VxtpfaqoueQ)#ym|F>;~#YIDQdSTCsMh|(2S zO-b$C128TqD=RlWgtJ?O?An&>KJ_zR;%+g|k!j1N(%crDe(^Pl!WRv5=FACgcFDd= zgdsm%nKQ?~J1+la{_32Lt<(+IOilgN-KUg0QZ{&$s4ir$ppUd0M(OKp@BOT#2pvt` z)pPgm6YZEzpSVt*j>l4YrNXTb-gh2*0*eJ)4!YI7!ofEUC`}oyj@N%^6&HMZZ3l>?AFRz;2D!V(B^%ByjsTGynfV4wUS>($bP+-l+@U44}=OGZKL_cxjgz*)rzW2 zGI|ye)_zalRLS_^)6VcpEwi}b*rrcw7>MO$>z~9@QSqDb46LM^{z*2g5_SZ9{s$x7 z{{jT3@!5SrG_y0s=V}p|&pLQjgT~ z^YrxDv0_TrB{|07#;L3SsB4zhg{v@kRn~Q>TWtBV>!H9cNTL_sk18(rE~iFcilI=J^ES23wv5zrE4u%K z&uJpgr#zV<6HUXI^b$%ax>5I4T}2MF!<_$>K8eH_O3W05Jm_JDvJTo1*^yd!_imo> zy8P57B!mBXHnzHO^ZEGrNLkl0NgS@GKpi!Q3zdoe{n$elUev7#i-;^Xl)LBP5PK+~ za{B23D&O)L-`j))l%pJWnT~?Y5gHl_;g09X?JEWMwrI*vO)~JgTG2=2tb9TF1EOSy z>93cULQGuXF@w#uYknlx15#Q_7?SQekdgB84u1I}fpVv&bQ={Ln+de{hDGuXsIpaS z)-0Ii@+gZ3pItqObtU@M0TGGh%)%J_CO)3t?lsdH+0dXz)$*C3D7ejiDpwHRdxU4~ zi!RwIeMs08m10;P$fvAm0r&5N_fNn|wv5G1z~wE*8t-@&U@16D$z8Z@ zO6Oi#YAqMo7-+CmEtD_MYT}XkKST*P)~ruZ?qZX%Uwb5ba$>e27(jpEW)J0ZSpAqz zI3mjo5)uFI-MtYRn^%KKga)O;oq0ivyi~-MEF~c^gjQ$sZOcc$|0Vz<=$$?g+Thu< zXDjATda>n~ZjJ>i!I5HwP8`$vpG?a)RLXH<&*YkFYJ@Pih_8Y53>eqEnO-Qt*9F_^ z20pD`pJ$5@j!%dP2XQZcV_9;>D?(>MfBLIYqYEFe^vz9~X{f9JE5Feb`eBWVdJ|V^ zX{iVAX|>rNi&8D2ATFsT!4t+hRd90e zNCDFXsS?EIx9vUu`iv10%a3Rkk5qyMHh}lKaK( zlH;C;Bnx%Ii|vifRYqvx~5+;iGi!|IrU7N2*() z*Gx@KRhFtFky=)kZbfxnqxID&Yrd(0Ff0oSz7{i1Ivu!eM=%en z=>{8qfGvEnX-8op^f(8A#nlYc5{H`?5-?sDO5D5PGEZIw*8(pVg^#vl8X}>p~sjK((moJ{fKWNX?Z?F>qDCNlw-X+_r6- z?=Cl5#htu7Yy2#y^$rS(U`ugsUE z>B#WtXjVHiP@|P^ys-EBn8%OZvR#ll(XqkU8ot*Yyh_ z%q|{|Xc7W}xZr#J2NWb_4xp+Nu8?E?xP-N9FT*ISPj=tEhK5`&ddjby%I)@jbq}NG zW;8c_oB4XjEso@S$#Jm$VMay<%Dl6(7F}^SGwu<2PRY-W#z>{ zj!&=|6`EKV1?o98TdPRl{C2kxgeFLTW1^+4)pc}qP)d8?_Ef`GmUcMXP+4u+ zQBV>m^dv0I$Ccy$mG8mSF8It&QxwDvt@FG~@T90;3j_Gp*Kr=XZF}|V3HPP%D5~n5 z(4@H6d9KnkS;kvHalsxrPpde1)TsW)cj+0mz{KCXZTpvZkGCwzSq)y$f_WARd zzdIqUw0!IiK=F%Eb;jQFuT(_dWO&?jfPVQJegfe5kMFGvtG8}GuWTY`*MEiPiREmv z%NFO#!GT)01ssmP4`Bi@oG>S-C{u$>)O7ndH%uh}0cSq#)RGaBckx<}r&VK!g7XL# z%!ZI#Se_J*oTLvQ#yUgVl9Lp|keW(vqX@Xvub0X%dZ*`L+4z~7&(bFEl5%KQ-@UGc zH*Yp{OSwAeD_fnsmuGU|MOV3k!F(Yb#eJ$~7_@*qQopdUg<8IjUlWb}yz@K1jh3EL z^S{l&ys@p|kxreQ-&2v&U~GDQW_$79Vdx>_7t9@MOeVXp4~|pp>1y6W5!qF^ zc}=H-cTIZPv}^D)$JB z+Xj}A0{`c!<1zPb)#-QrMn>QW+4@u7uTCwE<4aO$=#wYBIV04Uc2jq#$!ydw2OWm9 zaT>C;C4eR; zFIrJF@Xl!71S%9zK>kHHH=|n#_wSEqyW|EsoO$u}!P=ic)KP1qeL=dX{=+lNm;+zZ z)BEmg;N^a>qN4-uu~;PEOP(I=Y;2W)SU5jy5b@;6j*qvmUM;L)Q8*|i8MDM~-juR; za{FR`=19Joa&OI zsma?g@E!oeZL~cnP0ue(hc157@r`#m(iyvx4qYxXvgv7!OyjVRJYaH8tCBi67&Xcn z5VDpCh87{rrJiLaC3;zoCB=NX9tf7OPe4_R*n#C0p*)|EkjcHz3M(;zg^}ur9nCLh z(US3I$kAz*D4eHATgz4V_x(17=j|_@C#g0mh*fa>++1EtJ{H6LZ46UY<8)CrI^GW7 zk}GB=;92_0!EMqqwuJLOPEt}r!nfVAH~MdVHnQr5*Yc=`GS`fh6ekzJbSl8817E6Y z&M1RFs?9KUVpq?5l#^hLVnR}qr0jffO7a89piEp(*rwklBn0RSr5ATnGdUDG&fsC( z!3GmGbo97(tq0b}t;JB2*iLSh$`{_3r4PZ*1Rh&dxF*i5yz$iY>I^e@LgO#g{#N#6 zuAHV-3dF7Td!l>xtn}3%fpc>iXJ5jFc0t>2y48g(N=}dazE#Ips5>d~w2I*t5%CC{ z+rv+#EKSxoXbs3#2C*O9htVW#Wqy}|uaXrEI(9)5{S|dY$osoh9jwFNnRy??uQhMy zErIVYV2AwXU{r4~2_3oJb(S4+-bv{z#leZD~1)H~w&2f)ApmchLax_N- zucO6FY)Uz!p6z<#djP}pGBY>7uN52vGPhG|r4F33bkSX?wHb5%&A}0_EBD@NxToip z<1WKJts?yH%EvY-*_?*w8y{Q$Gi$EX1pbAGw(`L5LHw9R+yDO`^P?{#t}QR$<00kZ e4%QLuWHo6}diGP;%kY(_rgq}Y@uXuH@BS}~p2DjD literal 159804 zcmZsCWmsEX6D<{_P@n}0#S1MCp}4yhiWMmu+}$107AxA~PLN{739iM926rh?+#y&( z!p--+Z~NWnJ~uyePImU0GqYyRn%NQRstWkH6u1}|82E~BWHm4_us>j6JQT#akN(EG z`aKB-#uE%hSt%`_%mXC02bEqBEoxi(OrpI@cAZ@pHI6=_MIpVm*-3F<#S z-u8(75{Rl&i{BRo- z5?tQyxxey#@ngEP@lw3vG%J6EIekRMPN+%kZhYtnQ50DLO3Q+@W1+T@<(Yr$ekAF* z3VgaSBN8RnPx@9_+0fXS@BwF;yZ@JB0vG6Wtbp81#LCI4%6zC8}7XL%qh~>GTV* zltI~@fV;Lc;QZ0d!#_)YU{dM|ApHtU%RuoA308Vvj~8AKex$*1wi0ls_wN_|`{Wp@ z5ta99?{;|v1k7YD##F^5b{`9mwf%iNKZw^SiKx_k=659V`r--PUD9yI?Olg6p7B?a zV*mNKVMnC`ZV?d?4h{}+aXL{^=>iRn-1nuFG&FlhM|QThC6$%4yB_RgAwim&C9Bt; zKff{PkdX;qUS2LQ@7$XuXPPc<6aJBLol307&!pSRd{L=#=XbRo&2C0m|DHr=z9XG< zoNu|7#ZQoZy|gBEXRf`S2J6qC|0^^%uHplmET*Yp5-1#5ajK|P__`8t~hq^flb`u|Mdi`J$-#g3w13G4cimFQQ7&{{vuM9_&_WD-*0>?+C?Np})r+!uz&4=tLdin5 z$Kqh=X?Z@rI~+Py9!2P{ZHFSMO(ic{XaBB5_+Xo!i9e(j8d zTxs?^KihmOpHGI=*lcbV-t)dX5)+4sykv2GoYPwo&!xxtfxPwysmx-HKJ9&*aI72I zIrGOO3Q*3DJ#Ef}kuxq2h`T+2(3M=W<6_T#IHm+c|FzIB=eDi-_F$oBl8gDT^kuQA zmp1i98)!~2{3Z)koI8;G$U;142L}>d9v&V-DnXZ%Us9~!!h?f@AOG3ERg^Ftt7HH7 z=s1Xat*avh-*?`O0tho}H?~{(>nu2z5htw9<6w z4rkvv-sgD^E7hrF;p8Oq{h2Gnxzy}Axee1Bo1HD4-JdPfGk8Z=Z_HJQJr=ZN@)fGx zWMVmX?@>-##^VJr?8X(6z;e6651jEJ$PrTpSpn|ba285Hny4l5u9@pazjE$KJ~F{j z+2sLRnVWA2yie0aqr}ctll%6H|FKx?hD}D74PEM=@J+>xoJt+reA{If->1K*d*ZlI zYrD}G14$0*N!seI9HuUFssW|e)V&H~aQywQmAs92F)laC9tjQ zc4m1w>1%3gW+uHAxxt=J?Ntf!@fsQ$4;ljiUa@*xO*+ejTJU|vhvif`Z60?Kc=0AA26d2+NS#bsxw#dY4&!y~hM>L#&E zzlv)PvX`~eIjGYG{?dR4TpsALk_2he{Xymi53 z!IV36j?r}&9>$eEcT@J zED?o=*^~)v=CGw-cnJceRXNuF?pqOYqMZ))HBwLicYBo&g9Z(cvWVt%)u^KY%DV#jue8ba6v)b=9*Of zz5V?>C^fp~xy;14xOawz0b9dqA3xqBRpup;lPkD7UY*?aAZU3-^e84?sbKHmpf>Pq zqWkk_9KRh?ISTJ@8Z3bu*8Ca%etysYvCxlz93_>U9KAS-BBi%qb(vk0m9Ce3?YimX zUbBcrbF%HX`L!YT_(*xlH9^;aG6hyq2RpkOm7)B248Vm6=c`cgkGBz!sgpTua%@wE+@LIw@HTONW~XXyi1{ACot?P|`JvjGf023skJ0^cP-*61xqC^(suR zSd0azNk!*|s%axO`9dBq+=w|N*i%pKnd|hCL&m6he$+k)SxI`ur1sHPPmf%?F+k|Y z{+eJ^Z0zXB2sIT|z{#(BV&9;8@Spi0ey8Q;-cKyt+^hgV=M8aHRh7%t(ehb|+~M(R z2k7_Dr@@_776b7QunDxZwW-AeQhiz2*`vb(&CJ$2?yl}e|8>u;;BP5j1jZ#(4VT4} zMAx>4GbA4~9?R}<-F0M!-l>qobnO>)?b-0|FTzB^o4haa656j;{MiMiHP-tUXw(?p z-+(bkR*nCIjNx6QL+wiy>>?s96&0h)uA~Uf@2qT`XG7k~LjlE7cF7b)y4}Ezy1F_*kp$2F@S9cnRElp_Vz7MLr z?%Q_V*ZiRndjE=?ck|~qHECHj4krjj76`mR(}x!Es*;5nWv(CC5*&{w0 zkOV2n3)N84BVlHTMQ$6oiDy#}q)I-#s`I`SV}j#iy`$ItoyJDNz0%xVDV!X&OhH$) zPxr{ueox}cuPfQ-2z6$_{J3wOlHc61&B2bf z_AN2+K|TlYdn!(vyc{8imHU3gzShsyl;q@@y`Xm?OG}1rMw}@_=VxaQ_i8_w`9OMW zT-LfSDEXg14zr)F5T<%NqOo!G>DSa$t(Et=)bgr#Ojl`PAtN+c4SfMZDv8Y=co}eg z!<)fjbGynpT z$g9=xkdWIwoer}ZXP&!}jvIj@)vP?(RNMxKdFfTX@qVg6TY0Y2xw+>MfO56>u@U^c zqm9kZT(vo88!Ud@=610IxmfTv1K1djqH0^BbKz*)Eqhh04e}Kz|jym8`UMAhk zmkIH>gY={vM(kpjVhpe9+Ymqfd<|DRYzBQw;fpLPK{`b}if3yJh$ayfcIFmJq)iuC$gKA{V|U~he0L7I6z$j3rA#LvakJxMeuR&Y z9}^q9(g6a=%0AreN-Wk`cndbJf0k!!Zf5pL+ImnqDl!ra8{6OCKZVm6wUyzF3$m9v zC#SIKjI{<=of3EhHW7XM=1J5fPX3 zfD5^`I*pQV4?>^4X4Wf=-LV%_YAA6TN#~pT9L`e&WMN^M;x2%qGh0#L(BNRb^XgH+ zp+*V2uyA3^qAM1!<$AR7amVKxx54&Z2Tr3_pYtu1a66B8B$aF=xO<_ho@m7IuUG4BWHG?aCsQ8J}rK>E0-J1P!vcdZYke^8A>)7d|wkE%x%&n9P>`UA^ zWKzCCfLgz!lO&LsBkK@MZI3*#8M0pG2VIW%>~AE+%G?ipz)zV1A~@2<1kWoBbZOaC z5}dyG@#*yS$*#<0YG~+&|Mg5jQX52;Hy!tQ+ z4o(zz)@_IlqCzzLxZ3&R8)rPLe%Sx**RT%(Kb;LJBRAfVFr>u!T$J-v**~=MVH>=g z7}w?Q27K34P!LK#>$yK;X=w>;bXh~Az@7Kq(dxUx+fHm+^{m_503~yDd3kj)Ydk5V z6Sq7tM+&L#JQq<29;mG(2}${WO_e6KwS3C~yfg3gU{Bk3bs zXnHSvIhe!-4mcYqt!!Ty8+!q>biUY|h9Os`OLe}`N>pf+pl+denM96*j-hi4n`xRD zDlL2a`yI$jgEeOj!-_2_@K1B|eEq`^86kX5PX*gE;nMN(cfyBnQvi?LOAku}ua>X1V*NnOFW4va$}N3rY5+NG3tn9bLO9YrI<3MDkt}}Elhdgi`|_30 zj63FFA)5N$rXkqXOA>_z@VGb!MhaF{Vq(zVzCTl5)U)x>qJXQDhzY)9RA2X_Bah zdU|>ujb_$+A1=sAom2*0uDTOUqFAFNrTEOX?dMzzuni;V}X$%*@P!UI(dxe1mbJo3cCF3ULA#W}vS6 zQm^p%{TCc6nEzPu$-^&9f_QA=_8JL-jGOGzKl@`E>b-z%!lXNxIgXIikXH*bDs&{c z6G~&Q1-_?j?k$!6%`q#w{>QooU+xle>h!ZT3f!_Ew%MGTnVO%*Gt_rwW@7U3O?O>l zA9qx0lmwj?fs}+U(k3%|cfBnC3vE}W>ukfX4UWz%`xP59_#N}KLb{l}iJ{v6@%M9z zF~hGD)?i;gu6f$q!BHxABr(oPAvD`s7ut!jAh0dE1a+h-yS;thX71=s;-M#XJzQ{g z3A*9D>#dgzKWq>Eh6KfuGs z-#_$p-N%40-OfXU-s|czi&D{U>!`TJZtX&n){i?7Eggsh2$X_?!Z5pPY+;DABQr74 zqEvG2x~HcnPcF(Kjqe}B{}44d4QRDZ%j^~CD}w6$wv9`lvLL16=^K>F+LGJlITu9g zjk#x4e)auX$uig7EfZJqUU{^xqT_Uh7Io5rx&%!?*VH67@y^c<_8&int#%kcB_rEb z2ju(*Rr88!yu1E9A$_iQo-3EhD=-42n6{n)6 z1~$1dFf`S^d;h-heJSWXW7Wgkd(u0aoSYnVX$_LUcuBtmuu@at+6SAfpHPsJ%I8)& zl7-g8+NcWV{I8BYuYWWLBD{=@XaY0k`1t*`HPe5Enb!@jUuM0x(2QTZ zh%xkAA@|U4hn?)w*+hG8dX1W-QfchUWN#z!3LgP}Yo72U{Ze`f*Pw+@oIr7nAqEBpl3xq7a!)xtW$%8B0fIZ#4Ga)yD&Vin z8lrwgMMI;icQcwLvYVf*e~peRsy%g#<;e{=1T7ExdyvF%1cqrWsL~#JAFqhHu7}9f z(FR?wjpfQ1)H~!V-<)j@@!ppf+C1ozd`F=AV0v{GgwBJ_k_hLgXq`M60BrU-T}L9W zL{`0@{u4wd6*cnyq(P20d>s$_f72qqG}My=?2}4m^xY53GO9XK-O$7++m{ zzfNjOWREI4fD%!mn+RwE=G7RL^S%^$ciV9{*d9_7cXw=jM`(&TDFV+8hGSt<+bw)6 zERYD$?Ow8RbkwUdS!?t6P7~-E4*vFYXFOk@^hGAGtmC3r9oRQ2UN5M8ThiwaqL!hb z&hmjkEBNke_4Z42t%vtLUdu@|JF^I5EIb>*Fe+?d4y?xG*ifPCBUopLw1+0`8ZZ64GI8 zawH++Sn5996<(%aUid|55p&RjJ5-vEU71duHEDc&oSK??7@l?p0VAV7?SihuK`!$Y zmNip3uPGPq6|})ZX*Qbxgx`Q9E+Um&hf=z_&wKj;g!6Uws~7t^a0Eh>3eZr~p;6iF zLc{!zy+8P}nqAcVta(PnxRz>hV&{98Br@u$RT8oA{&))-DJ%3S0~ehFNufV~n#_2D z(fQ+Gf7qS`aytaN*}j8)=@{RwWp_zbnudbVY2oe)R5ZCO3PbE0-?g1{k4Zna%(&Q@ z4saiIM;$;>1>r$$^eJo(JUQDl%}@u{z)QpJ+oU0SO%vP{Yr~P3FZnoL^0f_|mrE3F z&54)5(!`o}p(K3zqE;>F(y}7U6nNq-9{?X_S^zL|Ko>-}Ogt=T0eG~P_2Dq_JI=e! z4jduRuQRg^u5UtO-q(kdFyEb}bVPst%*@GIRHd!^b*D2J`$#{ZbH}g{I!v+N@)n$S z(IUQ85Eu6}Ws^HC6BSDFeCNuC7j&iD6|nb72p`>U{m@9iqnk@PD< z=oDxF{U+9*n{SQEx1=ugzP^h+aN6S)m>l|Kw%M@a)9p@ece`|R?gbQOAg@IdL5H2B zdE20ecePSJi!Fxv<}>O!|Ka%#=<2BR6DAC(r=|u)7tIyMgufLmevrq6egBU5(>rK2 zHE=gi7J}M)r55*Fc^~nFj;4k4dl^^aDn{TdM%dr(8Jh6ypxa>`XM?5Bo^5_ie^{>d z9XBdc9O)4@O>wlehG_FXt~h6xTn*DH&`3&59G)lvISoEBMMO3BvQ3z^CM$R`aKEUDRChL^3cJ~w!)!1&d-iX@^yUIBqLEYx18r|u@^?&k>F zpq-}JQkDsTs>h5t#e?ZMB<+_uCnnZ1#D4{CobhwwyZ!j~_I5Q1B&_ldUU_%Md3Q#8 zcS^hM1OM}cEB<*=l!C6_0$uY`t`J9U8ws5NuM%`qCoj+Ju-TJc60P}uO}C_nFIUl- zn7>tt*qvqLCbLAf3d&Kvy*ab^X2g43{?WSQ{rlt-OdbE zw%?@{|2D!&apWnaRu{>(b~)!sm#Z9I^MpH;N`xN|F!>k`&HsOzYZ=c`qIDl^ZYj9E5`2=`nwU=?&{2|Ko!g7^vsX8d4Gtqdx1tZ=f+s za8oIF)NPZ%YJhfGTG}5ifK39_)V+)oC>et;KLbxX5oWBK9nP(%Gm+0QS5{)i$oYuK z$nMs{^We{*XjpTDv;W!vRwv0#6K_%bkLIvkkeXTIwuqH=b(WFyB5@pXZv-I~qg)&7 zbSrA0%bIrN9+Zb+C_BY`^o`oN%P*`erK^)9$3q~=RJEjHB{kW+40D09kZyd zkUm+bsE|MVf4z!4>8?&O4$>~2oE9%LZP#zKIsIP47f$G3jnj9!F%wj`ke+V0RoWYs zQU+`pEe(=Or;&sz!4Fg{IVrNZf=Rs|k@IQ??HA~zDkKo6>F{ulc4m-|XzoJh>^;UC z`(*^mE?jf%P6dcyAGmkWNb96~yn9T*?=*MPeKfg#%F z=kMQfvsH@La7z-ER=1?Kw>gVoX%we+Pow*h-?iFDf{m*4K1^6UBc3Uq`M9r?H|>XX z%>U9>bB|;RCVhWrW9N8jIN7k$R(jmM2OZs-F%zH6Y;pO>ZA18sc?&gQ;LQEU1Rsi| z4Gb37y1~D<~H9Yr;E9%rLp0n*l7f}C*4 zmwp*+2o9FqB;`y_h)t11sDTfi^czh_hV6}8?{=A1rtf+#&e(3<$Zb)8l&8!pBO{Z? zY=U|}xd1P_4;AI*Wi70%me{VmJufjPius6%H~xey#t$ZR@rRFpL7tY@;(Z(u5u;hE zMb%HP0t3k}lxmfjnVUf%kf^sx4UVhgg1pxoUzke2e@|Tv2|~9>uMQW<-XgzGQ}su` zAEprQN4Kkfv+FjwZB_tV!otGtPgja)lxX$ck|f%ep!ne^YjFF;1Y5Qfk6;}Q3;_OXFI!v8p|PidU{7B0Y1K$x3`3!*4u5;xuE6Kmme;<7_tjONo1|ZQmkA3bFm5B z!RW4dK+eI)@{wUB>HypBtK07eqjTX8h54h#t=DMzorhD8$7U$(Vt-lti5Fe)pVsAv zqDP^v+V35_#7cs)Zkn-R0lHtj`xvrWJV=S`2GP{%Zq?Yo?iDZSCz|%y?m|oo<9tPt zdP~o-0^mFaP!f8c<9F~|lmcx;`JspB%tema=1`)P^HNo|@ASXq0&R?8Q*q3(^H*37 zcDBBE=W1fJ)nEpd@e{OZ_k_Yo-^T{sofHA`tX&H+2kGUxt0uwLEP-CZ+&0^Cd53yD zJNSRS03#b0P0o1gSWquc`L<6JwQ&m_=Xpa%hnt;h$oivn1-wMs4$)S?w^MH z0ZoH&x>}KXfsudzIQtR({T<&FaRjJr5eppo*e@A#Kj7>Crl^KJc`(O5ZybotkN>b+ zj{TJQze|!PpA9~B3k0n!j@&W3wEyl^GryX25kLG_OvAwV;0v(12P0MkKUf@X*gwx}AWd&47y%;@gjAe^S&nU=i8KT%uHPO#M1Gy2e`m|D808 z{DC>C;TDLF1xv2MP+xHoemFL0UhT>g>v* zH>_qGYnptZ+CWDWHcZPRDn`nGSzNL`Y#B9fQA(=)l@?O-ncrhMki!^c%|?e8>^b>vbC6|Y?h#9n*IzWqR{3c3=|T2GORIpM zSZP)IvK>bxt0ZGmudM7LJ9!(@=C^*Gx=Nmg((hXyz;v;w!1KC#X0u)*esUsr<)1l1 zq|L9{Uh$OgA~}ckv(z=eYn(Xh3+jFDYsXB}=ZG5!#m@~%P zKG06$uvUGINA!1W>qAj^f5wy1h4MA4a~hAJ%U;YiLm^Hj;8eof?uJSeBGsQxDi8AE zu|fNr0!b=cTNB#TmFrqejLN^vm_F%pXg9XzD~h-YMcnzn~qctifPT zuiDhJ`ILRTJOYBn#^L4zto(<5zgqU;_2O1pPE?3>KRqo$3CAXj)177E7Dh++ufV9q z>i5Ma6tndpc$=*>TcQH#W`E+di7;Unu2*b|>Q@Z@9e< zqkbAml2J6dxb8P4SY@qfn$u&`l=}YJ7RK;BCo4&b-d%S|c-GtVoFu(d>5+&*E4n~N z(tO_&7%(WPdcI5X715&EDo<|>QK(_wdtCg>Tc7!4@r2IBXJKnxxuIj3%5nI@ZpF@A z0?3oBUI(ig7hy&LP*^t?;opciLAmff@S8cpzP5P8^y^$yk1m*$=h?!lZ%ejnVuGSj ziB@Wrs8_>EP)e?U@rJ;v(9E`#E|*La5ofIx*K>3QOt8(Xp-tKL{WIjXoJZo}K}bO+ zaOC?|=9a{{C24p%DWty0fEe6!MMFJg72-Sg_W{pCLd2fBTYK#tD2EdKxM+5gCME7G z)ObJn^I^t7^v5Q8fd1U;7&Srfa#|`<;e_yTl{y>n>8MK<>6Y+Q{^*!TlxJ118L_sc z9=!f{%@4jmSUzNj{&1?W{N&CWyw$qc&tjP%BCB%oZ1m!k)0#BcwT3gQv|_|cHMNgD zZZ7?Irj?M|aTH|Hx>TgxKTU~mzSW5K^T)F~#=pCKI7OU(59xp_O=P!6nPr#h-#P}N zEy~;9CFB1_k#tUX_7jILl|NQ>R4*t~Q-Waq20vnWWI#97{dn-_fbA?i&Xkdc`+xr4 z`R(*O=_0__L-zoWGBtE{`X=0*G+!~b#es~xB~_sO z_y}y+qL-`Qr?B6QIJ^qu7$nuN+MHr6cS(^}r6Dpi)+B$%(3(Ar6%4Firm|V|4GSBZ zqA>MuZ3+I1yFVuBpYY_wiA%ieLk%d7<(9fLC^eOf1|Z!~s1WWFUqf^O=-%-VA_iG8 znb`|DY;@e;aapVw3!T4h!!GBD=2Kx@4qJO_8VuKv4OwKhk56D!a}Kz5-6xIee&j-= zINF)Q=$)<-{DtN(v&8Vx|7={_iT@3%ws4YmwnH}S3R7nO?dt3}`Mx2w&QDu4Qj}F0 z-BpIEma8XZ+>Q+7za%nVFl`{=y<;a>EhR6v&B0z~0x%w~_CY_!K8E@rdgHz;^i{j6 z*txxtXO#e_o5NALap7M=`1|$sOYlrhcgj+XsmjW@Rh2`we>2n5hqi~&iq&MXT4#xk z3~cHl2*&|w`uUL&5S56dCV%^_j8}h?$B)}JHH;Bc+vTPoVe(ZfB`)Oe^cl?Q83~Jm^+qWlKKm#tG;t;DnDP zU*2vbSwOrD%*N4{`oCsP2(-3;6n$>gd7hKvD81OIZNYbDlqKbZu;n;B2;&yD}LY#8=`6cOQn zDc;~W(i}Zp)|D6E)AQ}}@_m~TG`slvI^_57L=;MVD`96RH5l5VtFD!qoc*rZ&C|ld z!reV#-odEmRb`oj%4RTP_-)*~cbpw?`I|No#)Jq=Fmzj}|8NCixI3u**6sW(8NkL0 zP*GH|x3xu2e6YJ@&*TzYY_qF>*UHa-Nw7(w@^iv+2;B)wwYhYze$mz{;JBi+%3I4T z0MWbJvv5dOdcg*if#~h&nxOLE2=7v3=e-V5BwP*EybD6srW|=us-Zgr<|?S zXHTv=IYDA)bFu(EF9sQ~)E3%Wyeoih%9JoO1Be%LB@iKjfSF^ht9z|ZE-%lIAF0z& zP$(TQ`FlH0;u%?J2DSITs9F+(wA#okJIBW@Za308)R#Vkm{aA`*%kWqXLD1El+ZOd!ZQru{}kGRbDNsl2tpl7%n4AEk#(5Q9z~IjP701)IeU!i&Cl14 zPfdB8-s%N+J|QQsyZd$C9~;zSI+=WOaxybRx))WE9-G8Qf*!9J9o5TGXWnTN@xGke z*(q)@y}IR{ZxqFD=M+fUB50f2i8l_~#8-Lq^Lj4z90v#bNuGFOVItsgFR8kEysGL% zhO-rRkpdM^?Z5eQ{b=7Q}qkXu$_zeXOPZ9`~mGd}kgU-)*4$9GaS{3(pQ4{nplY z2rEelE0G9x5eg$%YRkj{^2K}@w`ug;Xy!Qf5=w=&KE}r%$5Si@o%dZR%)qm;efuWe zX%rD{1`UU)W2%PjK2koZUsD^+w~wF%puDV9mzyaZ=Y}s5xA`YEYKn>lSJYx2J5!te zQ7z`w*?PH{-fH1P)-!7iDu;{03r+TF(q{38Jv+SO*Bi%a7u}|H7x-*zjo~wu``HI6 zvHuVo_ZT&M$*3$+tdqwPU({@>qatxEpR5KTL!Z>WVqkJ!ZOSmqI{p$QGPc^`4@DL4 z*s!Jy{U(W0cXM64Z94P!)*&GQ7}n|v8kUcfq*S2iGDSVl8t2Vc>ijF!vlA0rEf-_M z;PB&ih_}JCd+t;TD zIq(ura}@C!$21ZIUBai?&{7U1zf*k-WkCZ;1GR`>PrHgzSqRIXG_J8>4L66_#?%0D zf4c+)H8sR-+K%=2E2@Hb84YOl*n9h$aFy+MB(UY`(MLqHC*@8ChEgSSZ9$RwdGcX` zT6n4H)d}ysdmzCP=g5OlX+^b};tA z07I5Q4zApSVVADk_hXJnWP zfm%qn0XrXu<6$$tfU_ZDZwM-{pukL2&;=<{Q&El<5a63Yd@}l7f4R7z4+V?JP%3mF zENptv(Uu;&R=lGjJNL|9HGm{H4Br`fk9^11X<39E32!G5hXi&6lmq4sBzzuPI{s za#g%(IgesJZ-$%wg$>0a1e~^r*y1=y5$HE)G?SYm2FBG}<~(<}=smtYk*3MSX(*Ti zF)xBqgOgSiol+Rw&W^Ihyz$!Y;7&IBUd$VE7OsRClCtEB-=`QmP^$|GK+2^R5RaNyUhPzgB<>N4Pl9qimbbT#| z>HD7p8EB{(Y-wpGA|i4>KXY1XbXt{DQ@cU~p;1v$W^qwbcplWq{=J#AjmybN5iPF! za|8mO3>Yf1f!-X?uxPWevMfW6KXm5UJJ>XOUyc5d>LKb))U&k@KJJqmEG$&a``3#) zncNI@G>%TMtSqdo$SbT!E3MY6qHpSMtO-NJ3Gw;{HeV+*G73i$i{zD*bZC%AlyoMC`}@cNwbcT$ z?=D+YTS-G?Sx~#vc=VtvXbbkG>-=p*_JHsg#9H^>Wh}p`(M@^A?LI#vV_4W{-vG|J zVy!(+@jETSfB>`gU%6zQ#?6w{P5x16{)e91niBh7;AUrtGr!BHtVW6yY~^IGIjB=z zFI@Flppl1qeMUz|$Y}#^tM|57_(i!a*J+;ITPrFVN^edkD_&q@e%N((iz*iry1O@VAL zU%H>JFQpgFeu<2z$gxzoIY;Y;?ae z!i`7WG<3LA}J6*{>r6-P!?1F^6Xj!|^#M)KQ|FJJS| zm{3pHLZ#o>{EXsklV)++*EyHTd_WKeOm5-5L zzY)KI=DShoGk8j>$pgQMB0^%_1P+d}8T|p!&hvu#d_(7(Na@&($yzkYBbEqoUbLjV z7jFHL`)D+lz%GU`CxfElcuuar@LS=#QRajp4ULI~#RX=sRz5N2BKaLZGJv6ST%Nl0 zuE8sCb^}+@czv$X!lJ(8Dxg*`CG3S3ebO72PtlQ)u@N!(#Okctnnj0~Z6-YY{PYh? zhSRMka>n;VMthbG%Gy!y6m56eD%O*ct}m2%Y=ti;$7l_F%7ocDY^7Uloz zMITJgZ6C!dCQ6xe5u|prL&)+qdt}J5F(nB$2UtpSb4`bvmqI$7V#~)(zFnK2eMDTv zakRP@=gx|G9Uo;e+EX2j^+q!b_->3eka6he&F+6MWu+$FammR_EiS1LJ{w6%B0Ne- ztf*a;Q#_60?2x~~!>l0@ou1Nqw8`D{X>`@XEl|m$K5-$X!f?~AveP8zHyZ;VpAbVq zT|sEQtwWNMrL=}df~Q-BAwWR2L)UMoivLrLQo-)dPR``e;Ar(TjjzblaL~cgk$!vz zqR&90U~0I2$RUVIK10RIR3+GP(ObiYhKNEb4t8iDaLC!ST-6ege$XU}eVQ^er+zmw z3kF?mZYOSl&Zo)hL!%FcB=F?(rEJRc+hU~Um7F!>H4O|h7WMUQYIpr{_9{y47u=@1 z?31!N7dMxheFOVm&HB+{ZJ)KaT2{7R%1cX6pg}dpUZ-&S>8UgNcwT*}DkJ!Xw{!Jr zbu}UCI{f<}B0_Nhb}^7%x1VN%h89SF0=$S{Ha0grCBbr`|Htq8@J>EF1Go}BCyzKulK@{xKR()5RGy5#^l;L&s(tcqW1y%cu?Wt z19!U}#_@)iydD7Kn}4tZ%HH8D{pL=n-;|zrSPX*N#Myj0be1AfR#GUc!yFMCF%SB6 z10@8B3JXsxE)vs%#}+2o4&-R=JFu z4U%_=oYkGU$Vug%=P)oZk&%#suh;w+ADRv}F>5zeCS+z3QBc6cSMO#l#A0fu?L&W; zc2uTxNkulHi%&-T!f#$Gj+!0gT-8u?@i9JbnP8JzI18 zOt`$hG6jsiFu4rWYMt;pw5t=22D2@1oGD?$5wWx)`i3=b=gE#9jV>92gFhJ=`znD= z$`T%

n-n3Xk^W)5=_erD8YC%*<)U%L+-NC)O%EZVelgVX(&r8%JTw%aaz+O`*>n zyo1<|_V*h%ZrOW!nQ-ue$J~|Hg5<5NbbWkuteG$a7W2(DCMOK^)2T`2b|L&4S37Zz zdJj@kHa-}wp=*2WlVOJ!Vg}y|zr^-QD;&VX&Tg2ij(f~)r^%Rr z$N9+HnahtzC?X^q2cFC1bhWZwY@cG<#zUCD%@Jq5bJ#Km?S$>YdZI1-4cNr^(11;z zrq>S=+&jt(DGFP6>f@BBl{3Oz_JU)+80duD{Po~W4=_sDsr zk+IcYkgcrapPJYN3ML=Zd`(EPmCke;-|Dv+KW;JyxoR3Nb5K&Qsd4u@_N{0S;vOrh z`2Ni&j!0MOv(0S$QUTwzcDpC~6p^ByotXxAFV*-sSA80!9#EXAK{?o-P$qChNkxV8 z<+FN;7C{3^el*{!S6TyiosAZXPBfNWqfvXXtBZnfh2^VNEU#XL+%JJevjYQr|7Zcj zpStq;`rx*Q(J>PhpK-)7l-|5CjL%>z8DfP;evvTr02s*$B)Q19vG z(TK?KrhA-M6&;JNjtFTdxV%noQg)hmhHWkK^75JbXjk1UJ*Mr1t#Pw-D)khCCubJS zUaMnO6!m0YPN*j)if1<-I?XMMsazUn2kWHpzeHF|Rj4Ocu;*KaF1|hsUYe3zO|NaJ z8-MbM7@PtaYBAwE{U3|8H&4!zzX`D?My=>^J#J+ZmWke-LOl(==W>-W9VEmoA!`?nzBR4vF z7>pW#vW(k1I_8GV`tEoLFAEq4wfpYZH>{wD;T~hVwbRo{vz12Gm6MB;n(u;+3sQ{p zRavGg0=^C4bIEoJ}2i5aEePfq>C@R z*?b0H&o3`C46}V(({Hl#JlB$z%@2gNIM+L_Dl*9E@9j)rFrMecqtOB4*p_Jw=R+pV;@?}w%sv|2rw?9*<*OJ{OI4FQV)vLTYTLGMJvtDiK zxaNT?Y@p!+mUp&iFx>eO)%o!r1(h8nKOfn1YA)T>(lECy(qL|8zKWU`f%S}Q`kwU= zc6t0Cvd%gzs_uLH7#M&cQqqcaNq09xhjdAIcS}mg(A`LPmww5jeKfGo!`&w3q66%Agc1tYZ_)7Qr>8sb_!6@t)i@w3R>ZweKLWwZ)#gF{XmnI|w<9xU zO%Y^GExj5;X8~E9os&%v2udiY^Ou-1X*TWGO>vTgNh(XNhLgPVqREsc_nU1RBr~n) z)@Rtga9#bXXnzjW5pPD??q4FT?AVgi)|E*u$RcB+=vI4*|xw9-Ts9u!1|=L;=ec;E2^fxU`TtjBxFW$BScu{poMz_y32 zd7wtPbX>02e0T_nAkv9ftqlu|z;fzobTh<%zTxqeQ#?_lwC0vNx4n8r=GXtGc_LXn zRmy|Ni;3y`jPdX|)Zvq*kC^is5z(hQ^LhTL!yCK&|9ung zCwe{!8)*nWBHb1C7H8C1#r0MO9Pyh4rQQ+fD zfcS=ktXOq;VbCT|03ol0d7yyd>5dWnxY3`R^45tSEcbdKv+tP0i2*GC`(ORvd@Xw` zj~H05$C5d?k1l!%}L^KslBHMefg+aXfMzqbvS;6P-^rx&+lkGA+M zf`U}>JYLr|JhYEkK3YI^6N`+$Qp z9D}qy4=isE=xsuD{o*pb+o~lFwHpkEk7`KFd#!m@(;v4!9V55;vB2ivUYJfT7n&KL z8wU9;m?whC(O!#k`Vv_j{qzS3wm2>#TaX_@a)hQ7xjK$|{r6oYMV8w1CU9jgxvh=J zqEWsShev;0^f00mnQLH26&T`JnkDEr)mXYjSZFbMfl{=d9nFI7m%|kvaZ9xe%%xNqJ%CR~A3e^nM6sMI*YsG)ubeCk%5s?-yh~$!+KuG!F5< zSSo-vsTUFACa4fsYQ`UAEGcL0W0q2ZW`M`_+~@LNmDsxVsHsvO{0zJ8}#!<6G`nvw^=0 zo18a6d%H44OALMGQ1gQNhZK86mx|`}x4g60#?hCl^+0Keqbs3*vjehh*HJ!G1|?e0_=sUpXap zyO7%EEG#58SIV&UQrKB+Dl=@iUd$z-TbCvNaYRNmnPV1)krt8llfy;AMogZ1b6~RV zHtwBPtE|yZgIuokceUd=$MAI`%p3=8H=Xy`@%}&j1TpV*BNRXGQF#f8pQxBAJ1a$d zB+I#|qRU?`dQ4njxPTHnE2G~{mt>%2Yih>#lQ2MilU`J$mCyX1-W#}20=Gxf%)b=#NcAT6Y z5&kjRQGPF{`#ze%!IK1h;w|PToeD~YDAc-tYwdcxxjiXwRkWnj!QxX`D&q1?X6Wnm z9egD5@Z57%wpI8tb2MZ*Ka+EuFWZ~8{p~&TZrHq6s#a!nOb)iH@1#HrvQkwx8X;fU z{!TI-k&$0Gqb#1oHkao0nc1rYRp>;42E-zp1`e7HM~!I)uq?96hR2EBkq%etxJVh$v*P zFO1AV;P;(*ha_V5_nj8`mf=p9^r+;^rLe_1U=U2{vLKS27R>f{;2i`VKKY9OE~IPR z^|V_@im_^GGSZReVRmT(pGpvdHp7VUpHTRL8;vnTRK3xkg!-w9OL2DH{XYJDCoqCH zGEL{+yU%2a2SZyl^#;5qPvlY*8SZ}6Y+f@5X>iOfFzc;PC^|d#TYISQMX(CUue+5h z%bVgg5c>xGw4t_@b6swkn~RVZqLyUbL-N>+_`#*iPkA4%TH!6-w7Pc&urC4$Yu-#T z^>s1}L^QUKMFk*pOorPz%~ZYm&;5CG-!o=V$d=xoi^A|{`sdQx(~`f`5>~apSFaRG zeLLy7HI*G9-7BEj|AQ_wPl$G4rcOFf4w=h%6eXObSgTv8cczWj)&|CBAb92!kMwEX zq^aKzBfU#(Rt*4{n7zl@Yql=Cb(t7q)+xvig&mPDH|;&h_jeTN}N@A`!Fuf zlOyJFh%ACoCGS4sfM3$y{Qr~Z<$JwG{s=m3)EJ(kuH&{R9dz9)YAE{@Aen7jH!y#m zsA>fxE8a&v2HVUQb4hllu_yesC&0a>{%4@SHal&iRSxxpeX?juS)`V9ul-_pT+H{M z1z5=ONp%;567NiHEy*2*y2S>3PSPJ;lJRki=kL&k^KOAMW~476B@Lm|esX<*xr03h zXn`|jPpKArbMUUtmygl@OtCG*kS=qkB%~KDT4juhlGMg2aVyS+jK**%PZM|)&Wp$V zdN*x-+jW?L5;0m!?%#Cb=fY2$cfsZQ3=M#t=areeJGB^nbrEw$6n`fpX*pUtfci2v zPLO7$=V16>;`h%5w+MjX3ZvhtmdsTAr*s}3zO%!h(WkLJ)SI!Ih&pqwS~4XI$IZf` z%Yyyyl~VGjO~OR7MY5yBhynF9b%vjViKei%qXBG{9!O%K=N!p^_x*qDz!#$Upr<@n ziISlaL>_xt+L$TnZK~x{yYxRxpiWwramZ8J z;0Bcyz!PV=<*SxZYgK<`N%JgW1Xzh9>aHqRGLHN=Y#Vr94OIVqQ-e4N_2gR!E5ycu z*rS$=JHtgN0lV|>f8H^jm*=kEX<{-V_>b$*{n4cX%G7XOT7)JQZ!r>th9cYH2IKlx zO(L-AJH7Wmo5$^{8ZS29oLn%QhSk;GP8bVFinPpzPX2q7p4rAKw930rPwF22(T2;o zI!3WHQPvFm5)@kmX(iz&z03dpYD4}5+>`wO+u!Ur-HOd~_WDSYf_JM)|2$4Ox{*Xl z(pU~13G3c#ZGcHL*ShNH700kLgJi&cXZK-_Nuub_PUl)|#%lT$_4{0=gC-H``=*2;| zZz~IwtgUVHE$`{~v_CH$&M;`up`y#+yE!T@O-L!5_D2t7@|+PLK$epN&z_j5S`D;e zhnwwBI^e6i+@Wj2|2{!hYx%Ibd+E=h`vSHRu20Y^0R0s*0;bWzVDvI&z>42E?ERmj zX)6p6S46Eo*$TYaV=Y#1OM`z(GKNK)V$=%2kwCeo?(U)O5P?!zF}5J-d;=K)Nl9}< zB|~8sf2}gT-_Mzj(9d7gB{`yjIG##B?UI-CEMt+HeyujIUfzpxxaC}RKT~V+*Mbp0 z9K?u-Y18Ay5C#_3XN_t)W@ahccm*Y~pjE&W3Y2eVQ_yj60Q;#f|oyUp7) zx6;DG-Mz9_`xy)jd>Sz5_V%SD>8CUC*(5jjr#xC*at12sLFb59Q>ta9#&d&AH`2Z==@b}#xBSnHXY-MimQ=VIB zPp=hP(>jk+Ne#+No!lYK-gCJkKkve+G1Tp7n)s6adhC{?g{d4`^@017ubu{=db$?8 zyKJh^Vr#F#7lC`KghsSlBYuqXE3f zO6HkWQ&aJEDS@{|&dZz50(dS|Zdz=?eedz{&vuK-y1TkcRGTgrW~-2X1qFxa z**6sxh1lNdM@Nq@O?5YSvwIk9cOu5A%gORRp3SayUR*d-0|dJp7_JqyX5;>^6Eu59#iV1@P+|bh~{w8%c0mWx=KMh8!VtE*O)zU-(w^FIEEO=;19DaVz zVNYdrgSrWP08SI-WZ>7bw8_E=Yg9TPmii zNU`uG3c>khy-KH8_Sjt?=TU&a|JY>{@1u*l*&gBJHGxH7pr|ZXVj?yux3Hk#pZ8xv zLz5<2ncFa{!zBBV5??pLAXDjaj#1eq=8FeOL zxBbOJ4M?>Bv`M0>s%cGQOUwOvfkI15xH396wz#rB3-HjA{oiriShe1$Wy%7p^hfW@ z(eNe(lB4EZyTZp?uZQi53OQG?XRSs@OL=*DRuS%>G{l^grw=&m04h?}=acluBJETz7hPR<-N$dw&MPxb1=jJ%T(%dTpeC?$aDzIU(5!2JNc zjf4}A)noat<$h(KriZ?SETVIpv=!@1_nqeL%vJ6W8r`|-@1+!{4fN{NhG-+kOpO|B zx`#p|PhYd11+O-)621cYqtC{HzUm`R?GuCK2@ z^Y!iMYrBM*#T3blf&2k_jC!^4Ng$#7=-8_3Vnj0+kGG|<@#x+Kdab;c*KQ9Ob8mjM zb8~c?`~nw?&}n6*y`rLmJS?C!F{5Ix-bBI5$_fA@kz9`)EI-b!%J?g|UNCdy8oLr1 zR|E0b^ODR<;FHKQ_Dp(TZ!eugjx71r;k?t~f+`LsWwHD5Po;K2P6FvzV6#Ax_(z~g8QY>0v%RJ`BJ4q3%ie(6SShfjHnuGQpD zjoSJyN=!gN0O`duf52;Yt^qitzhAIgq9l`hY_SG}ii3uA3G&VpPw1H*-MW#~kYYjj z7#PCOgjMrB*t@>RNFdCkzp+|w_1(Q&y?R`joD{CuYC39__`27bgfp+(%04^WcE4yv zu`@V4?72BP&A`C0i2%?2vSTSBVdn9o&PzfY$$X*OW+CW~guP7lYI#eD` z3Izp^OK3=5#r>>1Y+-?`pO3;UPcbH17W8fT{$>QAQ`y{%=VmW^7_q1$ARtJmvDuuF zwhh~AEy)8FwY@zQFWBo;cK9UT``L8!`PO^D3U2Q(k#Vu%wLCc~?y|#q^swN9SFLu? zL+Ei0U;;ya?CeDF+?D4CjtH_^&Pm>@St(y*ya|fzfUrNVTY0W8Jk|WU_gMp?9#+UZ!tJ~Q8WC&nnN(S7Emc66L3`<>?z^IZEfWh11-Q{#&HO{w7_z? ziVOt|Sajk)pS{Gy#5|a5aXZ@@(sn;-xbGV^albvN1HxWk)$Y+zSxHHY)0L(6@KnP-HX4aNYrQzlWU~3bpZ}|{kw{|*x{JkKx z>qHHNo_BOR^TlRvz*X>*(A0#w+yGNYaAMCUEAG5)wwC=jhzYzm_x1k+-~9 zWONRz{2wbMAIb&_i3SXJ#Uu^ngx64zhcSjUy384{i^;bEft27tzGW3Vpj;ua-x+kA zkGl-wpBKEfh#!YQ5?|S}KMKdp_G_kY#OQ~w13JX4^F#u9a+5GDRS+n+MA}2pmu@Id zeg&}L7ZRf3>&>gnX<2Gsw#$1)j9>x)kVNL&JZrG&xYG-C70Af(TV7VxgeV#&=^F-z zp5h{(JJ`|V!_nj6k%nOgMM1&2TSi;@Q*BexlBv;n)EH(_5fM^Sl2fBE%A!z4i%}!2 z&2mY+RlL$;RGLQw0N{(+)gOaS6-&9@-!OGtT~QI$dYjRXjtSSN-Z;@pff6t1ODb9H zdA@^spBG1PvNvy4VNMezMe z$|Y*T?6z`p73I@{oLXVcjKQa=5F;nbV%4)~l7>Op!PXjy#Lg|C2gCSXR{M}Z?!iLb z!({-i@}>=LV`^Y!jPUJiI+K-so~5|s!0}nY=w%!`I|}S|&IqzcNR!!D07kIvT3KIq z;|EX)VwUB!^5hH1mvcrVhh&6T$Ft{FN*4tiws&@njg83-Vrrok$ZP9pJ6GP!+L*8A zPhOwYzB~BkXOS$hR9;Re-7y<4X>q*#Ms~y8!twNYdfB)c-Hh{o}0Z^y25djh|1V`DRAS3X%cTJiezYx}K^7z;NS7x&;K zFt}=@5v~hZAD~YB{Ou=%o*8AkhRt}OM6z4Dv(HW;U6;-3)Cxz&Ku|R+_S(7GK8VO2 zivv_0nC9dNZMK^X_d-HK=onaKYF}#gwufN>u*~+4CZlT8z|+C0*v@G+XkbkoOg|UF6y6?pEbYA*koYO9YJ%%21hKAl*;@v zmkz0MUSf6fxw&CbcHTN;N*)5%k&coX@(9B-*=YGw%cOA@ltvmhFRrnrrB>syEPq6- zxtF7WXuPZ$M%e{vyU+K+t0b*Om!H232soMdeU=ri;S>;X-ATa$#5ylCZQADr9Red? zGr!i_!f4yqwgxajimDu(cCd2*m3S}!y%X&0NMu&4!I-mh<3l|@9+ef+C)RZKdfae& z-|+zn8JSHn?-esCsnX2w$VlCCY;5WmKop@IzYdKF2n4in%eS3`er{ZI@53N@WMm{H z2Kt5<=l0X8+X^Uv_<1EKFAwlvkdl$1AR{>&_nZ}|ACz_fsRbb5+BOI{|45iSRuy)+ zi7QdZqSknijoN;F!Fovlzu4ie!yp_u#C4_GO~1}{AL2@&`9X6_Lj^_69F8VREQT_7 z$poiBlJZM|qHTi)Wh}!nU&5Gig=~E`1j1*U>O*#`v((nt;fWd_=;FcfBzjv&92M{J zssKxq)8U-(I%#p_=+u-*Ta}&d4?uwsv(|fO;NCqqwbXsbSFkfPlb}{&IORZ);PCp@ z_{?apwwn6w=_Xa&=Js-nTj0`XQ0^&~7fb@=$9s4DY+i~qx3Uj~zJC;ervrMoCfAE# z*-F3-|8oV-U}148mKESlc64+A8a`-ee=T(YW0k{Fg?Zs@?WH3^###I}AYP3l{IYcs;{mz#e=c?(pNH%<;E#ObrK981-W^5k=9tj1v@G4RGwP@^ z#MJ^;uPauo+3468GAP%PNu%G~koEUWHx*Q-_V2orI+fr$Q4O?pOTWE+HOQ?FTEbnT)?0qVe7* z3RJ@lE~D^((ydU~J%7Er`Y0(6Pz&))nmVuFyLw0O+*800k^vBMU=syw4LzZo@f4_- zN{JaUk*7O$+avU59PR*?&d0|mz4@MH(-$B^0@){kzKM;E9pp6{Nttc3THXVg7Ap@P zATq>|;2nica0Kt+-kt}5L+Ahc)zoxX#`Dxs!4A^lA0i+qn4E;;e>3Lb5D^?43<806 z1`ALT=%F(J`4C}9U0odlfl%D!h6OS+Yice6paH;hV)b~QkN!MACl4X2PQoE#S65f} zpR7(<*=e-{z~9o!?=-t!;85mFN4%{~WA~W5`Pr<&F(SM?eLgZY@BIOkw(@SXMk`!}DykZU%`=R>&Nua9T0L@nGrl(al$hya32 z44`TmDyA}YKO35k!D8GiLFT>R00X2jeSJe&G0+HpE|@os>m#0uwz9IE91xy$gENbY z3dsrXH`XH@k7gyt7~!)O6A@%mR;U0YURmp%DR86%uv-K+2vaWiu!|PAt46MLV7J@# ztJ~1fkd&BItJS?BKY#mpRi@5-t5eDKezX&CQ7OzESfg)V$c>F*hWMXa-kt^ohUDB?IR`#2y$n^3$nJ&v zCz2`mX30)U2lJU<=`sN+{$ev3iQMD#Ef>FZ^{F+73FmbaZgkV_;fBN~cd@tesWxmu zTGu4@4Sj_lao)gVa;4s4=s#{R$i(W^TYnPA||t+In>x#p9+$qaR?X znVQ$7*T$1Zruo6&`y6K~#Cfb+sOR$Hg3by+>xCiRMgyF)$74c#kjAh#W^;147tcdy zHe*L;^bU1@hClXbhv4=Xwujxedy=zgMM{N&7=pZ-@pzf+Y(2-iUPPq5Vtwg);ml{@ zU_Vj6i15&al-9#&v7COW8N?0`i-3Tizjk(CMU@l`aWX-cAZQ|1KHkHb@7c3u$ER{~ zaa}sKX4lF*8#A5&s#J`vpMh#N?AY-t#nrfHy;s8chezvk4iX&6d5{ngFv?ml)wH#j zc^|e2f436(=%9@67M48ew7MS`oG|cZx017UzNm>*3<<#FGE|Xrhs0LEBk-^hFq}Z* zpuBBVHFxNS!4dv7obU9hzYLd#o~deoOOh#V3cZslerspY`(+e0;`TqbTwmP z5^P%VY(;C7mJfTUL0>q>Fw1m5zk7 zN&~=|m|mH7k%v)(`_Ani)WKQSCID@3RI2F(C2HI^(l(89)r4#6LGQc;)tTCKyaN<) z9~;Y-31;otY0s0@uiwxSn*5tSaAe2KuJXak-yK@)3>q_yqM)_A7}m81!}|mdoFHfp z9GCx4z#$|&E5VQWbTrNSwpJlHJX~B{iiUzB^8mm;{>?`0;(5?8dh9Kq{&1!+o05@M zFNIWbVG#16-A_Elw-BlQWogN5&@X~$#$3+Ct{|Q;f%CIg?eSTP4^#*n5lrXnKN6E% z3@*5pbSIV~VF*w6qLFM5kE_)Bv{xtnn3dpG6Clpk8cBJDO@@f3&!e?(p2)$Af?e&O z4!vZntvY5D-}Vf?+6a0j;ovH$V%+Ia2Y{>LGOkj*0JYGoR z__od2I<#mym{*m=pvz3iEN88etEWY;KJ$#mE14e@N1=U4CoNr> zClDN4AWCV@Ac^USty+-OcJ;wv+5Rcj#NDcVICrJAKLJYx<})gJdN4C)I^BqMg-lXt zLt0?}Z0-Kz^cN}RyH|=7uAb19k6&;5!}b7hoRJ;4tsqYs64CX>_`|r7i>>1RLzwTf z2L7J0oi?PbVFdHU0%o)%JmM3H#ky0fgstutW8gCEMzX8_(U>JnCK-Wdl34Hl&v9Me z*y18&lJu*VPU`;<$9n7g98xR@peij6lm#Y*DV0#I`HoRTM~9SUI+dBOiXKr-!t{mr z%vI`W;D*|guawOuG)xseX0EbFZvy(>hIJUjDzq{DRILofzSU1aku)`_-NqLdiO1TY zL#+fYuABXnxm5l@pvn`V$F|on-v`Q*OUKUK=&|zH@7|41FOT?qRe~5rVRTL9d{6Xp zrCyjA-0OP-;~rZwF(%yMw&kB5J7~3QRip)z5fdBNsNsAKF|aMMkDXju`EUkfisF&U zrXKiGsS)2ah<5N!ioxQ8<)4n$@e?BkiI<{MQJIVrc8Lc`_tGgEON^rpqnV#tir9Yv zR3-bw1w55!YFnQ1UfEEO7Z&L}RRs&Gk}qghiLF{rcjK1{Ow287F}Cy#EHs)9r`v96 z5bMbR@+(tP7Q{$cKBY@Hm`k=>mG~Vgm<~phOE^q~!Scd#X|Kt_Ol=$DHvVIBzRprY zTpUQ$5d7V(jduoT87(aC%ol_av9>lhJx-zdYcf^k85yOemd^SK@Dt6_>D-JFb@NlM zN_hwIKfu^rCP2L%I5@}@;Xo3isOc8eVPHroya#WO56)?O9apyZb{ zIV0&F_pxVTFDZO2EzI1YE1A_BF`e38UG87hRH~iFI%K896eI?^ij+k}L<_8;(F^|U z>_a6q_D_Lif;Wx3XzT}Ti8^7{*u>N%KCef=`Ifdn$Y1wEoHj;DbZ|hF{N+Ob`tPw8f=!@^v{$2$ni^ z+>sZXVWspX)B86-4+j|qQ9?or@b#hX(x^l#r~%{}vqH1N&)N;t=z011O43qhe`*2o zB^tu)7uUa@W;Vpm_IRp(-t3-r`ug63VjJuAHv^>9J-KW`hXlpN`^5Vw0E-Lbltzu~LB)~l zh3kDNGuHN&gQFwTn}+)dp1YHmhKzZ-!B` z7hQplpDQcd+Fn&eUbD4Q$w(sW6<{(!0j8!pi=&<0Ms>Min}sxd&Rluu389xFIR?6n z1W9xi)@KIo@A#aERo26S94OhWcIjaj&jL0c%5#u3-KJGU)hE6&2j{Sb+i;5xzZ&2x z0)usfL;PJvKlV}R9auoZ>w+U9fbIdSl(y;0euG`@LHTI;VCZ1g_6Sg-i7lbrJ37jL z&%wZ8yPVbnsJwX`VD^&cgHuE5Znv(0aVNsvX`@D2tHmBFFQ}Kj4ZbquVRP#zAGq$y zs8KFbG-#-tP??MCiFpsR1Whn5I~=e1BMwS%9Q?XJb$glS6;%rvXRNft99KqGWk+1P zU9@8Q__1i(Tuc(Qdz5WOUV35gw7EqS5**&(9_969f1$-nC*u+J<$)@Ydj!AP&TP)< zJvsswM!ZPRuiCmAtyX7GUEPID8}*^JaRy(08FpI@cL7ni`K~h~2M(H8&a2^KaIpkP zxqvyTb_%ml+@e&oEvO%?AkX9ahyoaP%vjBVYz`Z5hu7ve*Th5qY^YQ5( zYpG@dc^fz(MqW`KbWzYl6;Eqi6A{1tS-pzKsGSHVE+K&>a08sg^u@reqocEkfUDjv zxouF>Ev?D(z}8BpE|7pb0^>pgV<(U&21rFLwb}$ety_NInNLl1yIibytSPCP{rcQ^ zXW`8U<}WH50LpuAana%OJOXW9uS0bVCCoz5V-fJW`h5|)?#LZbq;vql8OhUSry^%8~}l&wb>ps8XFsGE_P1V0V@_6mHG@-l-RI#8RGp z5r`n%g=I3J6{DAA-DEk$B=|QEZXB0#n)d}&Mu>5r^RpACo5j*oLo_DOIKcQ#C$iH^ z5U;b+ZzdSx6}9(sm!(0M!$FtGfv`a+{hKI@yebKX#QpPGMtuAOU|^b>SxJCESpvb= zys(Y+qUq9$%ZteguKh!(G)R&md5D{vTO_-pDL>yUV|l%gcL-{yr`H+kK<*oUJw1Xb z&Q!JJDciCW-(P*tNMKxheHus{BPY){c)U!)j8!r!WxzZ!wLkbj^oQ!Lw z(d520A)ZP6iE-~df^0aIy(X)ioRlRT6a&gVPF%?p9nllE*eWCE^13{)$X*7-1z4D| zjkrYq0{qak&Rt4SdaCHpML5dXe;gVTSi_#zJzfMmN1tg`DKx&1Lbn5X5njK}w0h+y z07{2GZM%mdf-279Hf6jl>fckr`h(Z5dwX}XMOzCCN~p}g6B*VJ4T;;XGx7)q1NLTnQT?N9Ar-}w(#oF_J0qvMyn}4Ph`ZcUGLt|Nqg4c->Xs)isGI1DVsdX#MBbC|BZ;Co2aOOyT%u( zHxBF!47wGh4KWi5G;t?EuUDBwdb)`|5gBvx(8j$>cQ7#MSQQvY$3|V^rQ3PX6)LZ% zu9`X8#xosvv0YfVNaxt)u}$(E0B8Fr4p-y1c@rsp4BX8DxhT1g6SY)J6D=)sNlAT0MO^{i!0#CEilun&(b56Omj!T|CVUUc zn8F403&0Q2(aA_3-)_#mxuQCJy@{^GQ(T%8*89U4Bw@AOEOHbtTEmQ;I7?ArQq3<& zh>9&-pzEftu4rGah8CTWAe30pcYa;QHO|0*i;JVCe(mO`)#iFLRQKqY_2sr3U)En2v65An;NiAC!pSNQd)A zK&on1sDUO`T~81{RvUoY)UYli1E?HaTny9ky;(l|_eix=S)s9)<1#=i-rinP+bW_& z6@~lq>dNIkRj~2VQtRyeyhY1yh`Q5$v&UZJ*;{dgar~xBxo*vyj1IM*>=E7rPbQ$% z+U}S1Ro%;-g1})Zw0Rb{(j#dPaw@`p2v&>rJjVCZJHrRb1Ip-J39j^XdpXYA68GJd|!{6>ch>%Z8eIk2d{m+$|0(sTLdyl(zp)k$$4(n%B0y|X9#LJiisv_dd=TB^GMhM+o^Xu|UN=ga~-H5@cy%S!tEh8mJOoXFj$@(jf>`mHhl>SPylaoq_V0z8xU$ z zQ~l*CgPnqcin@pysZx@Xw4<4m(z4f7t)eJ;!Z#1VYObKn`W6#YTD;=yEe85&Na;e8 zo13Y-Muhhn9P;@U24?IQwF+RVhmQN*^j@aUar6)NXA+two_LLZAS5JAwkdXXZKP

CPkh?(nk+!tN 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�x<*Du0?OFy4g>J0wKC(rO$NRVpg%q> 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 literal 94921 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 JX zSPN9D9o0-V_6uD3cZ5(27PLFlPgT2#R{B1 zB0fvglKHxwi9%6a$7E%?{IU=20pmlTZ?D4%_@vOc%R!npQJ@l!JZv>rtn3_1et zb%DJfi`UJ$x=CMlhlgKycw7TQnH@6F@6-R&hww!~SbOvtZFYX12VmCOjJ)H?B(b?Q z<`NR7%gV|&H(!f9i~8VDzdkbiF+{!VyZEm>M#Qs#fOX>>$N3xYnE^y`ggk6ZGvyXjfV@W4XL-|dKk`() z!nAx=+F;r6_#SO{5qiAe1T^fQh8ykL1As?CuJyKsT-teW-pt&5G}Az|z~S%)@lqWW z%phOchc!vcRcB{UfCnE4S7g>O$#7^DO@VS5z|=rapufY`n|Qr5RZ5w?H&VF~TR0_? z!n3rzte!i>AEWSRG0Z|LpVe&r=?*l7S2Uk}t)}VvBs&G-HkMPWeMxD(_X`1;>ZVw+ z4k!y%U@#aS>m9MtKD)JMZq{3y^aU=!-v#2{K9xKH0dE1a-I->vYx!_G>Qohv7$h9%oC&+)lLQQ(TVu9)q z;@c{4@9X2ABu^HD>SQd>Ze^d>-4i6YJ->eeI`VI=+qTONr$4y&9^=A;gM-NC z7{E|$ss?L$^n?Pzz4cem(!2=IrKr9?T0<523dZSZc$BFLu0!)~F(uYBjc#W}YR=9z z(YaE%tnN~_pFT~|r^4o~dv>7d>{C#eSq?dWWK#P6R5)Tg(MH4sUs`Evin zy5`T#EWUB?ln1|)g@B-sm@kFbV8j&V_>9OOo@!!gXlP=wbG?KRZ<1Y<$Ubzj9nn@#=`z6$s?Z&H88slH_O7< z*f?hWy5HI}7Xu*f9L*h>#My64FvwGv$yK#0JfI8UO?k34vD5nbHil1BSeWWIuB(SU z|2-R{6LRi_SJ=fgQDXAEcmPWaG}BjSrxsFZP^i<12a)jhkp}rTN-8;5 z4d!8?_wcx7L}un&qv7DO+nuc~yI25vjinybI4MQ24u19Dy#K;twI^0~%ri8;uFl_5 zfHGNv#M00*CL#1w@Y^Wc-Yp1R{oQk_%E`qy1|kg=+x0==L76{8m)~w-)))1anV5Y> zincSY6vrEwrLCc@cKN6$9P>>goioNJDIwu26*|KpEkgPlXj;%46yLw$5XKfKGb(x& zXv1&K5`urBIV8jND9PSr#-7i;*YMjDToD(?1S5s%f_1G-PF49P$Tm1UUl(3E=qQUg z+X(EJ_%$kSj7&Zap5^zs8!)ZqjbWnMQxp_@wlPv`d&shP+lR$P{TfWNn8 z{@SNq!B$hFr+yz*tA8zzi!EfLy3muepkV4+8=aN)xtR|-cz6L7kq1 zUYEt8MgQ9r?UBMf0#h;tyy0?pclV>OF(?C4gKce2I06(dF?WoPUD;55ny!wnKi4V1 z|1f*7$a4r|kn0t3zqv-9ktlA`eOFi4_SOz_qV_>>)`$KG+x~Fm9LnZ_V?A`<>vZbg zh97ECpL6_?-$#z#xH&*97jBmQpWhk(1O9rz5^FDDYVKfX>y{an`N2_9s{U)|7M_ra z=@o4~a~x}A_K!!TX;{pr3w6nt$}j80>t)l`!jv}_-wbxKgtQq?Mh!Kt+Eo@%LUFGA zA5&;Y9H>P+P@e#-?X95yK6tU)qWb^z0v`A-evqy6RZ^E3dhBn*l50V$Q0Iwgc3reD zzcP@-*Zomc@;iy~XYS_}H#RvMSC(oEY99v`9rWYm8tPkz3bZ7m`Dwh!$x#%n#5NXd zQ+XWO)!7&VUsRGH{Lkd5L*PwPjPQ@6$jI0=|5vf@M@bS@uiG^11pS4$o$dSkCri|7 zjHSs3(W_JV1UYiQ&} z+o4~Paxg<-WqbGLa4fg%V0GqcQE?GLrLouP`m<=FQ3|j1d`e1(1gZv~Y&l4i4^aYkAzGYLEzfjgA}NTKDs zGvA1=ie5qvtlPs?@YxHudKQMPM{W?YXcR+3gDc*%-ya;dkK>NP7ox+vtVZ+f=Gd%~ zA=Xq?_2yUel^zjb|D5;bm2e$-RxCf4momf9B2AkKFT_&Gs4$Z@GyqLk-+UWL`HpiV zNOth?@hRTD>*(tGTPEG>i380~ga8(=haVE_B~><*Kt1Obb*@Vy+PkPHCL6d+XNl5~ zM0QPx6uU94w-pCPlo$Zw+M-sNh{)Ia@Ne89_;cBpK^CjMOf)@j?$udnbn5gIgV)fB zdF#z!0d4-MxwG8x=?ytjk@ena4I}1iuAbQ(=q@pawkSE-NPUIrWm3Pj3mO_)f|SA1 zsM5X*5v=z1cU!dv&7?K8YTo-SRvH=$^T?4;egXH%5YxJZq&oYJnJO#jVWrBD)}d;J zeQI$kA=YG(mP==nbSSy=KDT`1N2*L0$yoYiZdq;eF=lqiMXt6Gxj`5KbGZhzSt@6w zSwSVDK^6r^JWbo@2q2@}&oL_L33*XbQ8Qh}oEbw-ay1S96R{(Esph{%Dyh97;mg2K ziIz;CbB5<|jV4Our7XnCqNTF=xu0|ToNNlYM8u-va2fS?Vbxg7*k4~g10BZWW{>l> za)WHim?E9rp<>B+9bQ+liB-mwZ2!)iE#`gACg=Nrxu1*%VPRp3RU_-Q<(BF;NC`bv zns<#FqF?V(Xd!0VLY~bOWY+<1O))Z6ZPKfQy!~Bjk_e`sMUvUA;vys8J9ZoZ&i-&e zpkWSbKvFoIDkQR3qt?UlSUB8vF9z}VLC-A;N4Zq_wC9(QEHQ7h_nLaVOltl+0MUfZ z^GHcaIa|(^yPT&f)@ZwqZu6&ty`)zt$iG-epDF%9BR)H&Ym_Bm;ItMGX*PcJRNxW46cx-3;FP=vEx<*G*`RX@7%3B%?0 z7e^k{sHW3Wj>i$;DzB_0=5yycPCws?Uz`paJ2^RF(XyNFDR(}5J^(-XpUa4cEjAdt#ZnN0be+^t_NLqD*i0<#rnDS&7n|a+W0Z6!Kno&7UnS0XaJv(!j zJ+nfkd}qjpt^M|JSsS2u1w5NpD#X*Wos#L~_a z&wfHXM7_G3=W2!8-pQb)W@`#hh=_xwB>Qf#kf0#BUGJ-+#5ou8JDx~bZ@zI@60-?( zq1?g*EL_oGvH9TdcD%0EV%*daD4OhS6<@5%rZ<0KZ`6EVxju)@IU zopHp4S>(|@?!%hXZ^~>H4KGJ4#mR6krJtC+oiNMTfF}2UQ*N-n<%U>mw>Z~%x8L`o zPFc=Rmf4NLki%1XT%0z)G0qbsE9NU3Y!A4_P^Y!HJHXcWN;-oTGP7eRei@j|Id4k& zgOn9ac8NKimk%rBA#l#|T5$&vwj}$Vq1&UlEf_t_V?=P~2rDltWXcAr(fFlJB6Bb# zIGD>}+f~!j^0T178A1*;jo+wi-U6~erUAGbsV%N+bu>hUlQv6iIZkuW4Jf46lr?MI z+aq5FwfGmos*0uRFm*@^nrK+*Mc2lR2Xp=J`~o36(?-9($5!P!VAHZPNgRe?dKnlx z^zA!MDbx=}MTKlYwQF3P^%1!OZjqmHJ1t!qLAWu<$h_G~Y{Hi*d^&yId`w(s7^t z@i^o~zT~irQ338_Esb(#3_@ggfaaK8Sol0iCs$FmOg>S(Xu24sFlFstyl_z3B!t}w zk>~Z&WH6zx8%%2fbBj2+x|>yLxhd{5qIGWtV7|P+qT@F6W4D@1rLf`KS9IPRNv_YR zHf7jkf6Y3VQ)O`^4f8tSuzE@;beX?;+Pb4HCT80|x%c{WWtJ<+YRw+sW+d58b9*kA z(_U}GN-&qpPMzzeIuPt%MHz$Jbdt#HxJ=;XUFWh@DRnJ;Ewk~%B)y~bIk0G|9b=Eh zI{e;D+-9|)sfm-BdJSjPsqzf-Oz>3hwiK1oe$UAIUwP_pn@lFW5SRV04+r=kL~hhYbQQ@0*<5jo%|#yOvfv z_s8hx^tXXmyTT!qUTM{~nHDcM2DxiIcs*UumOD}789?Xx3v~>wa--)KlNSc1V}OdmoppfkO=+uGO^j=K2h4d_<9J%9do^lND=;=!<>w0Ys z5@~5Sd6Uiaf{i*%PF+>k==(Oa6_@)>4MvjjnMrUjujDGzdi@EBbd^$>G_KR#%VVbO z{*KO0x0Zt(#lyPuV~EY-k#ov6Q4rlmexlmw2EY(xs|PY|@(`c(*hq@iReFteD=XFH z)a!#y7^LdA0bwv$3C!N5P_w!|F_BZn)W~R}S~MM3fgBBYxKMG%p0MF0Lr_R4YxaH| z6&-zNI%jJQbz_4;T~E(UyhVd!t>?p*A#}(JY^@c{)C*6kLps}Pc3hf&=oc7Y_-U(m zB@mMi%g$NPFuegOEXlPNW^3OkqjolAr7;V+(y{&YMp(tXCX$JY1|R=khu;jrd?Nq+ zV#Kdz5PuZe^Vg_Sb2FR^V&%Pm(u*jmEVnLZqf{stqMYei3p@>AUOmQy=sZL(oX+n> zYZD1^>FmPt$hDW0q!Br5SE`J&a=vMB`?R%~sIi{9&~}QLSZY_;C(9ES-wL4I~KLb|dqNVR!jw z`-3~)2!YhrWmjVq@NA9l$-BE2VBF{uyLTq-T|`POC_DM_1$%Z{z-z4ZcNd{(;K-Bi_DN}|H%cYGGhn6NObQtLev z+2oJ>m{@jpv3v1Y{*4Ocp^2zjfY!oxGyW zZAXRe?dQI&mai)quWoJ;YE6$C79$$#?8ofwRB$9E`wvM)Z3{It)W&>DHhN=s_O8!E zdu|o^y&fkw!Y%vWZoXPes!({Nvu?(Gx{!VvJA|aGToP&dvoh@?301Qby^D|_!sI7V zg2rC(A6#uY1-jgVMv;aFx3X)zC;vqsy#8!{j@zgCMswnKWTdmzEH;%Uhfebi;OjTu zw}!~IWd1l8(|TJf#ddJH?2igG9|oh{ZHTBJCx4pO3jAtwfzOAB1!Z~`8}IoHrE>N* zIoU3ju$Ow7>a{1udLg6DG+5x%1%7>O1FH=;n#l@0SFl$sQhf^FfNoyRRCzlYetb+C zR(UU)KMyI@*(~?yZo#Z{hn+S$E?K75Kl9XXrqn4vnqo-zT5Pd`m8^sns_@u|+Yr~g zUw%JU;ib$~sJGMU>{9{_Zpszw>Dv4a=?ESEY`6V6_EK3wenHgBBb=)88d#$@D_Kj` zAglSUP*^&@M{vm~kK3_P@ArwF{ZxRTlG|1(aGU|oRe%=3$4|DUQ_0s>s0L4}|9peP zwf{M@dadm~8qO+}dbKAQ;Gj1+!ddOMi*{5PidF01P`>|kw~tWTaO>`zi8!0Zkj_6+ zV;5*K7x#=ohbMOpSD~w$jPRj^A~HHYtIeb$7geyb8pa&ygQfdt)PnC|R@O5e{Gw668-LTfXQ`fatO^=LP*3pN*H0~g zYfGr#@jaC#Z0zm;myCPW4%ZWJEsO14sa=F9#0Ce z=_iHL-BPw0_ORx-50q+h@!R%1x%%~nmNr!0UOnVLRk?4=w}*(2sn6#zP@=|2>m*0W z+40dSnPBEl8j%C(9(tGL-&hMcT75IJo8@?6LD|Z9UP^q8X-M-lnx5aQG@CU zl7U~40>9cbnCW%aJB>ezo^8&fS_!*Q3z{Y$OW_0CW9Z1Sha(=oy1&+zWuwPXzehNC zivOnwTCAgP~tj&Sz>-$ z44fCi5o;UgW1@@mZpU&D2#JZiJAG=LodLs4F|hF9?sl&J8Qw^ne`W4Et!9n)AWCp1 zLkhPv+2s+I=}gY;eNy#r^X(mc!`^L5ohTu-+>f#hJhUgHmw#;DD=6)P82sNaQ7|tq zeyMmb$>pUo_&ik4$g8)k3qE`P933v1%SWk|qq$YFX0s^8xWZ-w4-P|piuOcI^9dTI zVuxCFTbM=s)>6Wt8OY_vOaMNzs^x~x!XjBOs|$e5sL12)7`hbVUdy*ae4sMfTBP$o zi2-6ksghAp^iAC(ot0pJV$VfDQ|TSFF0HlbBJV1=?#DVJ;xZpQzvV7@$H%AL97io- z;BiVQ_Aom?F)@A71;J|#{+KmaHXo;+_IQIK!}Zb*(65M&wdNo_lFIa29QM0k!?o%a zuEfPDT@rg4;CXp@IxRO~w0(RwNHbxz0;^Vc0*zG?eRZ&*`wY_&ttXcXFICg^sOjtVF)U&-!Y|ZP|a@Nj}fEeAJJPh97ctsv}Ty*r#GgOYdq_HIH9dWhej<;3uS6frw!WY zakQF>;}fTK5Ox(nkEpPN)$egT+dixk+~|d|Ta4}=Mt8$JPFHL4RR9*f;KKm`P^=Fm z(?|z9C4T@;3Rap?{!=_YpR=zdwCa4$7XrB@yg;>lW5hs6P+{*>Vc1KZjwq;2N#k;2 z+mJb}4m$OongnFUzkYof?Nh7pj4$3iJ`$F43lYULLRfbDSBg%2t9;}p)+ ztc9!-^ET>i!r+U|^4CZ4RZ>v|bo0$?hqAW;&dz5JCNi0pC7zvq*%I+Eh)2V6ePdH$ zxas5*LdY_iq)rPpVU9$g#c}<_+!=vl(XdIYt`KQfxK)yWVBje}M@;h0*|p1TNQaQb zQW4KqGQWrV-6KR3s18q_4SMENrLW-v_K3}0Sg3o16^{`S4+7EzUC{}vd&w>&yz&c_ za_MiMFnWFh)o*iL;U}{mz?H)SaWz|eRVDuWv571oDcJpKWpF`GuMbltDA#_rCy-f8 zmhfJEs(?Pbh}G$>s&?Gpj5)N%hnK((8{JNZz0n~%p{9ZiRX0q(L)mzyq zuBI-<2u{*lgD+#Jcq|pw)eWA9jUo=n|2b^}>+u{*2KH|fBt*K6HG^}by;Z?vcYS(m ztTI=MDuKTRbVN2Yh4%J#=|d7+^R5aQ96sgga7tq-`9bm;8C_q8q>kR4M)!=lpC#d3=X zFk!ay=d@ohP}AUws<$X#J~{AC)Bo}$IDH>>xI0;i?jgC9}pnHXNG_p|M3Hy6)6JoSo7HUk(fmSd166 zdtvX-*Uw}+uv>dllBM}YKbk>rhEEl1(?@MSd(9-6Pl|F5mb^_6Jmg&HTJx`pa?Ihe zff=&=@&GF#PKz{JqM~<^ysCJUYxXkzBZprAF<~~8gYYqmf89-$-bzkEi*Es^S8x-H z>G;<)e(wV%m>`!U=CgEuhwsZCUWu_gY#T$-=eg;NP27+*7wMn1i53M~-Sou#o==`W zU5BwPXdO4MjnoL4SWj&ljEb`fxt|emV%e-MsyKqf8Xj2NEEQLK3xEQl|JgTN}Rva*-FUzNL#jU5cn z8T<1_H=DWbQi}i4X)%7cag*4Q$cx8rR^qxM{h!9)g#*>il0!jOvRbS^T4YW0G$u`W zGMCfk&80~M0V5OBk=toOck9DNpPLsm@*fQir<%Q#>D6yqVM4Mx_f4hnJaG*FfYa>h z2T}fQg*53eIyo~GCNY%~DileqG$PXcn$ku|FP|}xH_tZF3Oct>v>znL(O;z1;=KGd2&}Q8 z)5+&4v=d3mXEu_SGn9%r#32799~Uq(yuUv>^VAv$P!8Mt15q4CzR9)dtt9WW1As+0 zsGU7CrLSe?73(mK3Hj{8Yqr-U;irZ14p>Bd2j-I%g9jrRo1*@R4mk>WCPqf7`Yy(@ zsSw-C^0D}nXD859KDYI8yONvbOJ)Ql^mIHb9tjLRE@vFIv;UD{$OmSZuNN_aF^%$pH|j)E%vI+HVU=ISxd?7jvY(KRtX376hggyr(ID-55Bu;eUR` zO2cLe!@|W9Z{WAs{wTslz<00<3SSv*RSugR&ug1{9h;GYJkrZEmY{6>`wdE_dE~~5P*SceK4s{sn&aKw1O3%iUb`U zHJ!t`cDUwne>U^h!+yO_x&a#(S6o9ZHwcABsbn%=1KqmM@~va7Goe@t_Wx1!)lpHc z``>z0JSu_`0#Yi{CEcJP-5^~`H_{9>1|i)bIdq3~gVH_p(A_n}P(#f7=(*?q?kj8g z$1Iq=_fz{DpP(AUFNGpQNgRokBbzL)EV%?gl%+A1*FCb1+8MST=%aTeViAym2@5p> zF*}ePGE`9S@e~6M!d#8{&!7n>P;Iy97ucKiXT6hbvhoa}T3;vE9oO<@(3fYIgDA}b zee(XF1;2nx%T`t??Hxhv#<1=VaM3qEe=alJ#3Tg~oS(ER`a9Z_O~rdIXZH{?bRqe3 zYviU}wmZx}tK5=(aP%|v8I63OT-GJTl*>ew`4LleKO6bu$1Fk(p8f_O%GNSf+OZQ% z+D=j&Q03z1FT|_lxZek(v@&$EwDSuGMraC#D?%#e0kGH8GpT2bp|#ee1a#EtRQFF$ zHJDbef6aO@Scs9>Q}t*`^v52K#$3aH{aOTgir}YZ3BC{Ne`^jW(5bW?_vW1T8JMj% zQGw!MHg<1Y+gtBY%kkprGUxioVrVU$X&;~41?Q`uBAWoCi4Ce`XJtl2K-^`?rj(5L z(U#8Ssrh_8gAD2g)eE;A)o`hoAoRR>eJ#_SmzI`R>+8Ej{yX*nk#I9c$tJMlgsdpylGNyCAE85IaMeQWKr#W)=eP+HC>Ywcv*7e2DwAo5_iGPn zY&JP0K|P=+M+w+@>Jn$VzZ%=~NHt`L07y)f7IqrjoMEJuyw07?XS#Fe#xaLfY7Ix- zhboS({1L;y75iP)EFFx|udmVPs+CE25+MKu;zG)EUWTUnIqg=6opEPOOwyyXza(AC z-m@{mxjjRlQyxY#*?6%6Y~57zHQ140dpxbot8jm6sCrEMLSLfk;R{#YOXU50fh;nZ6vTqi zsw{87yf5EIe*H*Tb-@FfrHHJ>nrALZ#U0cXKTEv85klzW4C$q0Yzv4c*R2PC2ZMg|Fe1aY1tP#W*HVK=a^hRRw&6I zY@0DKA=4*f#9y`-P92LA0ehA>wTH*<5tfNku*DgYlzW;YUg+1jSPQs0PP9T@HyS!; zK%(LPZ*3=TI7;}S)AdW5zMOSoX~g3Uih?&5Kn(;((R75-i<_N2FeC_H+ra5LRh8?| z%~${J#oxFw7^%M`GG;n>@7_H>H2QG(+x|z;*P>B_x?}a1O<6NBve0w0a|QjmX=xw64A1UY^cMdoI{-otLX9ipiw(TOtB+=XroIo9SEan&f7$&Zg9_lq0LuZyxrS`LADV{|pTHKO6_8(x4J>ZhXhu zNiH}bKEB}SkiPlc8U)%I{3>iC^4j?CR=7MHC}&`kyqcLxd$); zT}CW}*%Ob4{@N^`nB$U#wcAF2YRexQ8p<1Mz42c^fg8y~vXxkO9F&KY{jjitU!Fht z;w=J|kd)9$NaQfQ)FP>n*yKn&jL@Xv_PR!231pqqTfOj7XC9G9Tbr6b$#SZQ+5TUe zF7++8Zc|-rU1Q_Sya4;R#?hC%aD!&!{>XOv0wYaLO*w1uFmi|Y@o2`lIh?VI-hSoP zrW2KK>(>!o9qHk( zpE)6_{XuFntu3wOJ3EE}qCV@VM`jTqQ|G(*`O!aJusDK8SE01t7y0=3fJE}= zr%!%mgY?e<-fIn1-Iv33XO774r-t&a6k3x^78i9|2&oy5!Nv6V-hD%U0o^j z+?Xtr*Gj2|S-=(^1j4c_Tw1;)_&~8_lCvq!zNRQVGbOv+lg%`6>?J);1TkJFJTLB^ zwDK6h=HNl+7UBOR&M_SJW=Vu_#56##NjBmQ&_&wX+?<@8@bmNS$nHC&YmdrZ>$kQf zsd#B(^6S)_(q89R;!n$X;iJ*$fuUdDcE|zdV{kBhcs)Ek{M)y`o815Rt0UeVzDRVR zdrCn8Q~=+bSdfsAi$gdSA5OmQpvSY8&<$pMM|(u;GnE6+rz#W=^BUi`^?vbSgi7^^ zjNXMRYlCuOt+r zpQ%NTx;U^li#@GV>x!Oy$8eYh@9qpNk#9d-86#PZHNlLqd#x4ZLC}5K$^q21vB? zXZ^ZtP6(D-V^xG~ybRv>Fo1WjU=;wN*^uRil7+F2M_5B!2$|zgxk6R{vrgFqQ%+RH z_JdbU2r0G_M{_k@HQ97%Y>5ce&yiX1z;^B9fp0X|pT6ml{&%>C15!}ZL?oQ>w#NYl znUO1|o>=|)o2ny&d=R}R=MAMyKCdSUi?=q*zp)=!{R^JI@ftlOdzqu;oiD>HA|LVQ zsH8yI=Q|7JIb+40DO9$*+*#-+V6GLLB?TMN#sBZMoZhlRl&gU!ojrE)^NI&-=ZWt$ zVbdl}8(Oi#9O?JScp|c%zHKa2_brU=RP~hn7sLph>FibJe8Lak2Go$=xQ|$oiMk~Q z;mZ0Esg}#^K^&yG|`@qQc`xnV_sxb>$iYRVI0duV+l!Pk7%;+O1atdyVbwtlx}7}8^k!0DGheL#@qkX1K5Y9cV2xpff{gkT1L)o zWs4}AByi@5qnX~I3+wp*?=|$P`Lq7v67u1Ox5i%smM~!}Wz`pT*&p*J0@Fd%;dx!~ zD^1pa2Ao^}`Nv+plK7|$Na0W?$or*DcXQC4%ALl))|?aHox(?izee{3=5@ye%4KOi zlz4j-Q~Fn88~cm#CmTSkb(}qBoaRCj{qR3u6&_lce6)g`dS*3-w+1O=3xD1s;(1zs zzA{_<;1{dNt9ZZ9OAkUg%%ztsd#Ej9i%BX5?rP=mdBuLj7>ReLOTjAh0#W~N;b&rm zu!%~g<~3|%rXKXsP=@LiB2hswxjCqt3_DuC{EHSXm0Lzj8*#$wI3n0GamTJ7t8!Z? zrZ$YwRsE~d_s3eQUm-9p=5;S{98J>;6A#%076)wn_v`g)gU$U>=cnn*cCn1x$!}!i zX; z5x2NYd^YRAnJ>5grTexq&vOFUo8E#lY$$Qj)2i&b4W!f^NRiA(d$^U#7g@=jv!`4pwhQ#r}d)TrO+?T2~>mN1TA4ezj z@=Ie7lQ^KfXE)`PHZ6?EOe=U^sc<_{nOrT&Ez38 zgXEH?0MeMj@Mwn@*_IDyEo3M?D;I=iUH^ECf12xAwmg4p-ZIJ&XTUardj-EK0- z)GFh)ZSnMj?682H`mXX<6=lsK3oCRc{P%%e)WeRAeCFE3trZ~_q9uV!xgV1IMC7eO z?;`xa8$B}wl46Z*OcTEt40fjRN30^b7iDrr{FE1c&%D+Q4BjPT|93=hd}@Y$e!cMB zeIt?BQiix`3?lW`w^w^$F7@6}T5+sRb}s>ZO1?AgxBj@#bd6`cGlZJs1;v(xt8^sK>_9Y z0f`2q1vqWum*rE_!NA?FEGuHbWPdCFZJrmv@txB)SXEL38qysQ*-@JX)&Dg&t)jEK#tq;YW`%eIv-*gz5 z>dFIGl<(MS@&S@^z&>SevD7CLkGVJn^lat?c z>^Bw$HLkMqat#AogX=GAYft)+u@UonhJ$QF*Ga>tf?Vl2Ii1G5Y0LB?zy?r*S*s5F z&jBC)+-KNK{N3k#wx!$6XyUU=uTl6jE@x2@&m4a1zZ72*Y+MPi%xXwTzPS3UxmM^t zY_DgVoMQ6aX} zN{}G~Jdj=Mc(RVmPQBCeNkYgpP?rDTly7_GSH8~rf!&AOE99v_sahgVv-kNOtTT@I z2~b?dp%B&{xy=1m-aGi%$T>2*5;@A1sOqxjdKRLGvA<7bKUuY&Y6;neZpF|Y3ve{q zM`d$ajY;GU&OMi1w-us}Y-<+LER@9nFH6DU}td}|3QRuzFl&jNQ>7`(X1BAYM79LBk$$5qC`cm z!5bnSMgDgUy;)UJVH&&8OzSWMT+f>788oZl^!t|?wKe-vQ#%672zDq<%nk8GV(s!w z?N(y#3;);K7JW)%RrFGBNQ zkig1&OD_+6XOS8m=bVnTgxuY3~+Gcqk-* z{1gA-YChs>a=OKni`acf_~QXC+-!9nW#wjRKc<$kM3qh-5E^urh*5o^_7~OJS%%Kz z&&8%B6*b%=5i}s)Vg_%x`@?4XK!O=SB=X*;y_k8n0Z>)HAwU2^MN~4s#^AI!?l`^o zl@@N0$nU5>UKsjLrQ}Tpxd*NzGU0ndilA%E)<@RFYRh`>Bb+h)x|5AYFL>IKhTT9) z^Gn(BLfyr)?veV_EglFu2_Pbq^a2^id3dUc`CMK&ySHEM4XbUJ^P4XBJPZlWy_|@b zHDj4eCG79(i{WQjT5{h28j539S=zPg$?g@afV@M_;eDU^qmgyNSZ<}m?3$y7;1gB@ zoqQ+Y76x1z@k|A4L>eWE&!bG0&}E#(Y#8rDD}AxkcY^;${If*7oG&@ zue9+EUeuOAcvZNIOLvbm(0M@}?wGhv?SSraoefvY&O$;PH^g-wO;p({i~WA@Hm@oF0xPg?miCt?euCoDShIfwh*M|vKp2(ye`eiy!v zsJ=>_Q;YK6=z?cP`bncx(yWm4dUqMr@@QCd z?C{VyY5fyFoQaYF>SEZeCw0|%BCkW zOU!wYMvs|5n#4wi`{ESylsA9-%!kF3f{%~Q#?VeR=83C0d9QzoE-B)dl;Y={?D2fl zQNMbZuiyCRHEj_)@-tE=Tmt^wz5;l1pQF>ewLULBGl!UPd4|os>NVBye0P_dW$v^l zaY;u}gMwE-Yko0O&%jzZO;aIlzvwX|&XaA=^r=tC>XiJdO)jtAay5VRMbX}SwpS)! zGqg^+53kI&a77k|4HS7rg3XT^NYAlfh>EX>I(YW%x%=+T zBmY5sF75A7IW|UFQZPPnfjY<*DEF5)feBxf4n$gc|9@4J-&I=4jGAmjT!-iisQ@_oII9 ze`^7vo-LrFR(q)Lh4n69*JgY)0KWqpZt&xM^BXZjM7q3om1QfyRe|ERV&x%#j2KBs zsp3uvXzyc=qwvgR6dU&DNO&B+AupmFZ$4bO3RJ8maW?Hf ze2}((B`!+kkIJa@!=@CA$Dw+-CTC-vwfG=Q7689b>b56yJUT(cbwIBsSQ~#ztC&?t zC}1#eMVn=3N4wVYI4fvvsGgkPRW-qypYBz-fRdF4vyLFNDj}Odxx8H_+H$Pw3UrLX zhwn-q)c9o%w?Df&kLfAxYDauurg3`WgR{&use4lleX3pS^!!c}!Qbp<(Y1=0U%)G7 zqTb2_u0s($Za-o=MhfXHZ4V{1%Y}I0{|MWNIWfH<8Gx*+5zI=}BKuEc#to>+f)aupy{a3}=gObia7Z#77a?e$G z9|J2TON?rX(g(9FmW^9AZl5a-zd!yOM#2A+P{mTwgUxZv=j`n4Tvpw|SCm$H$cmEk zyyS0`Z7fqLwM=aKs;GF9Q@#A8ARjWk(}CWGXZKVuR+KM>T_PdiP9ddyE|ztfW1xF~6+ zXmrR|>&TO!_o8Y&l`QU^cduO?ZG{Nn8!kDF7VR4@2mCZcuGm4awa}*X)Icm5$0TUx zX;V^2n1&^{>|`6py^K|@E3eM!eb1E^Mp*lYEPU{p>oNn7%GBTEmA9BO4`|ZglZa^* zxv0g}d@IelI#gkMJzgnaHbJNU0ObwM8bN(e9b9UiGNoVNX*@UsvUa(G!Zat^)srQz zuxdvAXBx{rl<>Kx8Qc3@={0-F_qK(TPnl+xp_5h^wxeYdr6=D7Hy9z(Y{9A*cWbQ~ zkU516b@KLvTpgCjRRdEitoS;rU%4w2u@lBpT}%COZo$St7o+xQg`C}UG~@0m)eF34 z$1t)fSJV%u9_1c(chsJU-S}uh9P6-bkLD>QpIW2DF6f;!K&}GQ!$D)XSFKP^+7Oug z$;-(v8yfXSGb=(u42g892nK}R-C+7nkfW`Yb1PtN1v&c}q%Z7&b_4j%e9|hzZqc6E zzl@LADJQCf40$bSpFjWnBF!JP#*;|qseMbXC%~5BU zo6F#C^v@fNGgTu_guM&)mO)rpDOks7mAnMrq3RT5EFfxw*$mbsn8zW3wDEB-qb_piPio4=nZhkpW~kvt0h zbG0q)LN{PNqH|qBamxH=k<05PfCDJdeml*OF<`P002)6ZI9-1=dmU|UQt{6beJUPq3v)3p-DfAqc7s?#me+Pu<-(GXRz6F zv!Hvl?cHWHUp;}^On)AJCvbG2fx061cAYv%CJ|D%CQEQoc{yGHKlUvkAUiH@0G5T% zTmnVy-$W}cgi5q_bT`Y+)@`P^CA@e6yd^B`kPAqRY@dZn*r}>CZu>v!+G|?$8hb4z zUR;HB(jyIzE351zy*US$^PcH-!pW`+Bc2UD$=x!n?2b^iAZX*sv(eK;6a7slO4jOR z?pGWZA05&lCrpb5-V`OnVLH^qtozIHI?+em{Ea>;%eb^cwy5NiQR@`bu|Of43!vKU zFybMgPEUbPcI|n^R*!e*X^Jk>g9JvsO~K{%HGIN#+;_SKsLVb4h@lE;)T^@6E<~AW zcWJWxj;frSO$wD&a`K3^-ch`XtJJrU>8R>4o@&X87dEx?$?Gg$i7~JdSiTlf&++zW zMWAgf*4vh53Up8*KuGyl=&?-j&d*D}Oz3QU((@zQ=DgKk)=v$WIDLmUWusEsI*SZ@ zL1jZ*gxoj~Rcm!B9F3!-^fvx)-y(o;j%_|Z_{v)Sda@!fk0h&LrZ=~%i#Cjsuf9e_ z9pKb-&hN+2G16-^Eo~77(d%YNX6_){YClPYT4m~g?Wn}$!DE!#!V}ZUw74J!GIZ+< zx^1;u1>Cg`tMtnG6#)TxpFckre`%&b4lDntb&|v<1dt9NujQ=eur+>L2I{!(aB%R< zm$5+tvD11)%@GO|0!&cI=|GX`{c?QI%YA+G_Rg?K%wMaEUaYoHLR$ukO?uRb`AlDE z=mWEz zqf*62N$0;b=e~QSawY#@j3=uLjuaruj5JfEXm9HvVAzq1C>Y#INMU8`l;2?bn_S|4 zGmS!`TCJrs2sm{6Bz+GK4uH-h0nd7W9L(j7V!D}$MSIuY8Lc91-WmY=>Y03iC0M0Y zdx?vBJw8W1LcK|K8yJ{NnfB|%-Rr%j+motx%bZ$VH&D0+s?l^`Z@pC_r2Iz(_JfCN z`Si^)LA>?anwlq+(Y#xe!##n*VUvz4nQ&I5B$vkCOhqqBYhg>ZNg6>+)ly#_0F{vt z;TtRmS}3bwTOu;j9`@5SGwFZ>hI+CZlTvN#f*kYj*=%*|ZPlwn6jOT5JC-t~QQr9L z)|Ewb%?<6%AgK`~{yEQUH#g#A1zKMghBQ{TEF{VK-5ixwOB@_6n@H36RN|}po;DPs zL?0NaV)kxz0+_Ah2cfHq)OT+zc<9Y?{96{~8+_>CyE8>Z)pBMzGL=sUii<0fqo)`t z0#A{6+s%iNp**XwmBZ@pRg^XDgVgpUnqwc~m_G>$KjNe-KD)Y+99Qmq$U77ePtm?D zah)DMGl!Z3ul()}VXNxMQQ4j7r<+ZupTB6jYfQf_$F>K=MP))a-@f^{QO~N?Q>%pT zlQNoTs$zjag`($@=wEXa@OO%=(#gcKj55MAT~x_1v?ZG&yg)MgXHjIMieta zT&cPhSL!~*rzK$K&n2vW#OM)s5|rqYF}(D=kCNK{wg86dLAq?^gM$gVM}Gy*-FUKD zo}2H`vk4u_tz=m3tzsfj7&P>c8PmC8><^3>O;Bc$k_tB{Qm$5fQ( z1(4!BKv8#(S<`KU>3q%UH>oYjd1uhpB}_K#X4M>P(}XZTYlK{&=pRe zyRt`szp^W$UE$UZVDC0_KWNxh(8%`za)GTe6@_aF>ox|D?F`7;b(DH8xY)U~jSciE zs9sd^aH!P{WEc}Q-^)08HC*oL+T?vD=h4R1a-qz{&7H;^9He@wo7wasxJ8(OLX(X$ ztLxi0N!&&{5ugQm*(i__M&U-t^scR^r_L=vrCKl(zjVk~(qGS>aLPLkwH_Jan38HYWcHeO~T-$f4=OOU zE3=3a4J4yF5VpS#u)J#Ip)kXnxU|{oy35%Dhi4{Uwi_O1lSQrLY!nT`9nqBoi=H}4I)?_0KsXOdR>Twgch zl>F57$`VMGFgzEYn`}P@6scgQ7xpgn?wTi^3-A=-(6BJO$?REhJQ^CNBi-gehWg0Y zK!a6J$#&(KQHHu$ujv`)mStewyCWj;=m4b}G3na~R@W$&z4hBvRLh`~er%;aXas=o zps3X3c|b-*n#W_mvrplLR!rbdbkE#ZkT=nf&TKe@EG}v96t6QEw^f?k!-(dB|Mm^y z?KOLq+IqZJi3`L}+yiy1t)57bT7(&s_1T9>nE6wyi^Juo^@&YkcnIv5=(04-SgDei--X?a=;kZC5t)jvns6 zwSW*r3F!Gp*)3?*e0va;5XaiM%2Q*MiGZ*{F$U4r?3TDjK%ucYaon*x190F|QYf;D zMJdOs?evFAo{A^o!`YK30ZT>sQ*UNKR~TOMH(;D-X78k1_t6#{@9j-R)6SXOz_oQ# zYaepnAc^!o#Q$Jr7RRjP^3NVXJzO|l7H~Db|AfV1amFHzs`W@nweTz_j8argG)2(; zwMMESa8galY%MOyQFPvTW5c4~WZGH994JD`uuCJp4|)ymi&w#qUpG^kIy+gbG}E|B znVde8UvB1iJ`Cx+$TR+P;5)qxm0mD)aS?pwn{EcFRf{Pi5Gqht9~rIBKx|GHYhHgz z#=`*d`^<-nu&YbT#ww7|2}(YZ$u$zAqFV{McMsQnv3IPLnW52S6c^rxA-Y;`B$82O zW?Z^9aJ*0%o-V(bmA(v%`(%b(YN6Vd%_8n2xI~ZSO^F?Hm*^Xf+}^YbXk$wJYWdaf z)F68=L08)XI4TJ9uPru^>(+{Gwv-jQr(`vtn(0JR8s$9}XX*n!$2+A)0`q}~q0GEm zRzDCZ=E?ln9}M54&c$BB7n#ot_!4~52E+rCguER_0S?p;TkR>_@nl<3GPSvT9x!(oe;jWlB z(Ni;r;n`BrVzafoLsfb?04X@!3-X$^?nIbMkq*yn^wTuAgr_7T5I@xuGJ@f;JRQso zAuessjwKpcFaG`DLBGL|N6cp336&ZKn{5&^x68Jx_lSkO%L4N9Dno4ME`h(_lKSG8 z=46bm_w`QqjBhU;gNmwF*Cu{vofA?mTlWq?$0t-`EQTA#YNMBL`d*f3_1=%kAJhhg zj$(j!&!P=>;+}pm`VQoE7Dnc`VvFWp*$#6`SOH3pp!b@?V33%%@9}bi+2hm$f%}Ue#44P1pFiPBM6@TI#D~|)(9(=~ zd@_Q(%O#!@5F7M_^#G*a!+CNYy&O<&H$kLlAneKZZ zx{BsdsdvOK98gL{g~29XVYA^I+hYQph+0?GJ!Ojkl*B3$#~{P3=S#*{(Gr)$)$*&p zO55@!BRq`x@Cyxfe-&TQ8?57USPkl@wF}d0l`l+dYx3bV@UFb-Lu}*rl})Y|YAp5= zmI&Y@n&-UcynenA68rjve2ad(8rYoZ(d8iToo)-Q3mUkhPIA?NO%8j-tA6#2OhYcq zz!Z_BCh1?N{U3Vqm++9#?;xZ*O45Qc&10;O7d7e!<|!%<$3n{wYXz7b1c2Ltnm#`h z3;UGUex%O??;38zQkNy{4WfYR>cOPvfUk;|Qe|DGRnU&K@{_y%GK35X@d@nw;qI=* zEG%Eq4+o<*?p3FrJt}V32t;W)8Klc#mQeBK=5uoMr^u?k8R%Z1N99&!M+jMue0)z= z2Pp`)>~A^&ozw}3~{ph1DY4-`sc)Bz(dy)xwC9sN9Yb>|aQK=L#< zJgI&o|6+DAqeIn8adIxp@?tzBqf0+ygOf(L;h^&=-GOzYk?BBaz3=zS8J_COtKVakB*JX#Egg-XQ{RscHj4JO*yEQEE zmz{QXzGgsV+$=JsaR(5F;Q$`C*SfRl;x(078XX5HH>1eTFe6Evu8Y+_4WO5!agWe5 z{fS(aI&k5**}cA`YV+l(mn^{ZE(T#it_+iaz5r+e=C zw#4M&vjW$8b(U8<=dxocmctCx=7>L#uam@WsQECJQY~a{ZM}Mvvq-%Dwe&WC)Z>x~ zh(!Q0ck8GkFV*#hF|ydEYim*HU1VD2G2qXs&M@t6QLl)7@;H0zg7~NTB zgvI&e?#wo=KeAbm-gIQq=S^IrT&u)%;G-Q>8{Fw*vXc_LE8hQkt8%)sEHzrDNt8m)3zDadYO#$2J(#WKT3~QE32P1rN57kU4xsK7%ZJCOB z@&*Tw3RLrKJ_gn(aC0PY2Xn*QG}zg1ry@66Wmx}hBKIz%iUq`@k}>efZo!E;Lf<^& z?F;Je$V$_ zU|?-I$8PyO7Lr#(&{166CcdIx#Pc=bt0S|(SeAI_zH3CX#z|^pbNy-MoY}m3gJHai z8phj7c8Hx?ar01W@>YJRclyW=9RoW3(j93^!SB(RVFa9>b(Tahb|@-Zvozwb=g;%p zT-1p0%XVcacDkPMa5tZ4uc;Mi1aYs&Nvp!V7SGr9J)ifKYDJs1kFOM6hlpIrGFax4x3(SSBLf9ERiq4p^s5j?(A zZQVXB1t`_BS*V2O3mG@AoRT!Z)e-;ODl$s-39~lw>Knkl14@EoqRA2E29m@Ed4~gz z>wTd`5`7GrA{G{TKnt_KTd?*inX2uqK&1n34MO7A@!~U2E>`! z*~OYof;}R>4~STFiapO3jf)s47>C}dj>ZlssPt@dFwK)QvMLc;d! zOMQr5Q)yWE@wm>j>3PvAk&gX#MuRlNzZDTdCk*QO4aVI|$EID{W(#w7DVbF=rMhmH zD^xDJdK(>qG(EAZw8TJt`wANrqU(Xa;&GE`;uG)0_CP|NngvSgWuAjD%NirM%wzS< zV%p0mE!ceYh;UX6T~=nM&-#oLVXC|)@7 z-)?*NKDbVRReC$g`34e-`6TaBvn}R4^?s0e?fUNQyKfM|i)|z;GJRoF<2C?(a8?T=bT^`!wND6D7YzRfUOzr#t`A8k6gsezv+6OgS z5j?iJOk&>5^qIB)B?JDL6b!hvL{7zXRy?fk#!&xGaR5S>vmbLyE9jWhq15c9!$`3m^4zGn1pviGJ@1!E1){ zjyS#~%hf=_TKC8hFQ0}?_>hG6gUM^+Rw7n)xT_GU3wK>^ckMclC;CA0`fT~MH7wV8 zm_A47eBjR)l)+2$ zl;dqWY06ZaBF)s99i$wSf-N%EfBoL^m`#kV*{VQD+}$Btv9f|@N|<+B4vyz2u3bcb{)#1!v2ib%gYlfhSL=7{ ztd{+(s4fxumXs|UeZQQ;@;NT2e|3_3SXb<2ePb2DwB$aXhmPbRSLInkuI4*%`OX$z zEsUyexo#iYV@lBD{7c_Hx*bZ>nhorqY}>iGd)Qnd8Cjc`3g!$t7)<@F>>959^k+pb z4*Zo%s-amub)q4d+RMPjul~_Mi`X+flD@kY>!J7Ikfc$R?(uwfYcsiam0UcTr|#y_ z+IqBbxfb+N*s)!LeVkmYtJ!qjAhXg2UFd=MAa-~Dbbnc|&TDQZ5Yu!vGXh&LH0PZT z87ollPdb=R;JQ`=S?HbCB-H9DhO6diIN-U7K9cL};wz^r13`Z5zgu72uaReFgbse{)pT?==S^-yHvNy5nyd~rXi ze1Ji{@a)H8E2COIYGB*$59zn z3vPx4%}bgTkMT*b<~>rD65ZOvgHDRm6%Iv7D~$kJ|A_}yk3zQTQFX97V zFSZUX68F}6p?6NG^@$Bay;%2rsa(;Y*-(SA zy>YK`d#`+ece$3xKu$&`A1ZUD4}+$}#*VL~%i`UKG59;uWuOfKsHTWBN2zFvz_uFR%>10-4bpOv){6KF1&X=DWVQ1WLBw|JVuBd zqee;^&n0-VYaL;5512M)6z+cVT>z>-o3Z6{qfTKr1M4A$r`&Aa*hw+>RrRJnrMsr} zzKF2l38m+emonM#dPvtS|7ipEZxq*!Dx<^)sTtP8YtG~(e0j6FW$*H+gNV#1)>3PX zPuNff+kr;0%&IPp*TY%8eTmIg1Iq>vo}egSE%c2bum+vO`19p9hi8R%pP+I1f0+6@ ztWwsjUr(H6Se6K>)qGr>SPV1jFjgS!;JJdw9ES=toyHmXK>TnhPr`W`4b}Ve-N2WOb&Y}4ut5IQ$YK0%)?M|8W#xiSHZ1CJdW0s># zFc6;kIIrBKbrfGtl<8YO@6q6-d3ul7KYn>XPhMDjC1b7Er1MlvwUExR3OMd97)Y^E*G~LL*%b^hZ$n_g8yxDcJ;LU!7cJ&jY%= zLcVKD!10#XV3uP?-A4#8QBiZ5JwBj?eKYAd>5bNEFy7o6gR-{aAWR<8ifqm`f`tcT zUs?fD{GJD6aU@XM5-76sn$yKbFO)(^c<1oLP8vgW$t%~nnL#qnjp?z?0*uEwAqbR` z*-Z{VeZEEMzK|9j9ewlG-NMO<2TMnqOMG^#yzCAs^Z6IQA;PZ*`bY$`^KZE8;CWLG zH8Zna?CJWZ#Ov&ttem0!DIjNv&E}@-o`NE~=H*LAxX02^r)~3bRhY=;RAc9SOv1?U zu=~l@`8;FEZ^h?o#rjTuk*h+F@@C3ZkFdRN z>PWk~w8=QHW^JHI?T-6sc$XFJ3F$1VPIg%8R&$xYs*0`l=5d;MewPwY0f1;%{3*T7 z9S*2(-NpIazf}UeL^DmaaXA!|jo~4^m>@k@UNO%^@tHZw{4qtV%7+Pfk(4q|KJliK zo*YGd>+U+(zFVHsrwM&mO#yS+KCmFL*-H1p*qLf$Se|1V(>I}F*B-yXZlE*x0Cb=2 z8m`7iY+&8|+0!|*EVUa;5g8H+fN(m_VY>6(lsRGEe!Ixv1T9EKMfJAzbOvf5!L8UZ zUN~9qk4@?>H=9xKjCt9!moYn&54Mre+}@^{ii(Qph9{;K_e$@Bkse{_RHY^ErHhg| zD^U6YF93nMy`fvR)iWO~3zPQ%HjFd~Vx^x@ylLHncu*EaX0 z+XGFi$^~FoYC{q;qlH=pi8_0=@VP`%;wyg06bHP@YjHJ>oA1@dUb0M#cJ%73AD?oz z)8=SJ#iNJoG@tvM>Xp(&347vTLS_mbn4Ba?f+{*GYOW|=7&ucH4QC$I{u4m|KBxp5 zrdX?|j#2!NG5PZzxa8ig97C~Fl`>;9YethY3JTIa4&P_D)^v-%?p-)HKYESfH_?v1 zb%j2ip9$Zwi=IaDY5w@Qh@t6=55bjFRD^MPxPm ze;odviTGeUjn0;c@9amG;l2UMO>Z%e4qreJPfXt0nFJ&fca@i$_{=VLxvQ%^iBBvCaB6*)OML=5lfcBp<&4PDnE&zj6kDy?LMX@^LHRyEnQDbdQB zkk`N_XuveQF^E3ubsVZE1nJQe7G2KY1O4eQmNwnzJAsGNDkofS_+^_qc0-2}=}jTD zpYHM1!6p1U#6oWk3U;RRQGD;jgF~LiC(4XtY*7u&*Sm)2hgl%KF{pKb{Gs{Y(Hb&r z7n>kljcS{T^B$OJan9yzR-~}2i1(k^=(AUZ@f?+A!gbuvtKN4B|uN(Z@`OH8xw^I{P0JDHBFuQ7Fg*)_IA{tSlCTrb6Sq z;m5!Knn3gU!hJT4zw6UIBeib1%a$!NEg!yfUor?IT#f{*YwK>!n>ZBT-8ehdwf;mM z%N%y!pxoQP={T=H6QmbC`Uo!GBcf#>`n}VdSCIr&MNI`?^q6biCOa()`5Q`zXpMu6y~E2|5?cq+RiT zDBX9J;awHZZ`Z(2f4ywedOmu8Nd51cbkCTIH;PiAL_1vln2)0F*H7JlfL>(E&YH-raI&xTjD3P6MtwG^G!}|PMHl^C) zynUuWPhioAE)&nv(ht`S+EDMe*!Ov;ohu2AO7?+q~&_k|0&K2lq=O_kTgqxB36aX^3{I^CG_PcrR4LMa^I>ZEOJtuJ2uVY=prsVVbF$i(~HgK ztEc>@^UZ5T%sOVFn}}aRAS|_ zny*&SviJ~DDJ3uOb+oI&uIMYlOGpE~NJg0UUvrS9Ky5Rga#>bEcCH6;94VkP0a~!F zG|9btU*Y^m4I^7HNT*&klTH;U8{0vIe@X(s^RN!GA-2CWTzLKC|2(hqFq&keBcsJf z-bEuYo z4YhH4;~*z1KKJlsD#X4h4C!+r5ZYfz77rw--EWaCxrB3t30=RAr8V$48KKa-IN9}D z`0StJYTN2hSu23*OXlH8LT?qo6$@P*uA&sT$FDN9B`MUZY%Cbjbi@dlmrTCe@$=2qHbSI)@?mu}yl!&lc zyOO`Baeb;0&r0yRO{}(-MZ27)aho>TuBI5`_5&CVT3`S5f0wvXi<`=mE$SOcttx{< zJjiNIo1)na)`rOL5Lfw6)HJz%P)y6WbH{O*g@uKO`mD!Z1K;8ghpZmjWTz=fN@#d& zY@I{<;b2sxisi2_=i5)I!CCwLSOQnj&8(|tn;d#b3B9IR9c~L)9^Zuq{+`ww-^z7I zKMh3hZjI0W4!5WGCS74$-QD!Rr)MZ#+=@sXV`pAlwhEl{D65v*gCw`dWpPQ_R{kG# z?;X|j+I5TKwxA+lLsXiGfQo>MNH5A(Y=DS}QUz3y-b*N9tAMD0iV8><1nES22`If6 zDG4>wOMuWz0?ApwWbgNW-}{X_#yRJX@tt$`c>nN4On&8g)|zY1xz_WAC4$@T$6v*> z-+MA)QM- zqPcOOS~994ibl3SQ&&$pM=RH%p~DhSMt=X?YFqf#`Q7m=kWE+B{c%*Z`N3TGk#KyQ zaDP$dlz16sRu9OV6k^6xL$GebaU-Qv@@veN$;rtU#nnnQ)zP}(QTO++#&hgSZ|;+3 zfefD7tTN+_BowshU>&cXI}rB|7jXBMDT|_EGwN%L%rw0icTwK8D?r9*TU1teDGVAg zsd|-pU+1cTS-!?eIHFNkx5qE()gjSOpNr0)zEADHb&>a!qgV#P`^)%Lr{%5B7Zi~! z$Fy)vMn+IaQ2PAE-q3gN-YqW4TvP<~3lU&pmXTu~_P*~u+8WUk>w25<10QtHv(UZu zu~H0h$%OxLXd6AnF=e^y9a7fY7Uj!`c}(5iLmaJ;;{I-in=@2kz<-q zgB%CaSKZGiG$PmWWl{*71_uj?xHHac&Fy{#yf zU&|M0=?rfE{WJ5KGrax(16R?Wg$D#c9CyQ#Gym9U2P^@}Xk#@@6r@eXozML0rdRM~X z;7}+)Pg@Pb0Uza!;Syh-DU(Y~PaBn%Z>&4gk?%3~R|ikMKRBBIDL*GA`(A%5udGuo z{OdiGR^E$N6Pl`>0gqcRJwe-Of4hyj8n}t3SXYaeZE#m<)jHk$a1t{ft(~MnbMF5B zI4Q>aD(oyc810a?CF2SHxOj@6prh>1B%9C}*frYFt?t!O^g>oQ^pa}fz6GKx?^7)- z*&9I~vixRHf5$R1nLMo#T7T6yc@LJsrQJ0nJa-WFv-<+%Xrlp~ft{NOY z*kPUDzt4miYG|S4zK}!RWbVu`kh_@XMbR%p3LlU5 zqE>MlzRC?&qOP@|mLku)_qYmp*Pc1Oe^zqAUsIJwJ882a^9`3AH6){dwZ}5Ev7utv zYmVw4BBVY^>BO1Ec&R_39WjgSUat^4Abe}8b8#^~SW&2+<8L6v`r3nuC%qxIqU&oz zO@806(*ie7M7qd8D?5Q-B&9PAfv znGYPI68zE&oUoVm=ZdkIGoD_5G`t@Cfj#eq>AJ>B} zG0^~|^+%lHkqhRxv!6)iTDTKYF<+b}L2&vI*wtl*&#aJ(qLPW35w=g~+f)s72Y#j4 z55NAB%aMy4AU1cosz=G@I*zl0py8uq;xm-#iv6>lqCvV!<@bcMk zuZWlRDUM98_Bm>V&0$>$1lJfZTy?!nAARTL8DFpo3qT5_nYDN(mh~+@~ z?d~p3$Sp2-+$w7OwD96{!&IBzyq28)FHc^o57$Z29HDxBdL9F=22bsm`uygUIfj};8u9oeB{HYJedUw?{+z*-m z{hYm$xAVY7P`84 zPLX?Odf(+*;&?Y^T1CXlj!QZ}#%U;0;Y{J|Xf+L^>;W~}yxRlb6H7HmS!m;(I!5bL zsp9n5=reQq&IdwIo+SmAhy=UJ4xUke2vt#z&4spQiz~J7lqykTC0X;s!3y@*LtdlF zlSyz6Ag?!mU-)xaFE25sHP!X{Bdr4-B!lmdlHqv0OzcK$#T_jzG}XOl(4Vh#u-1?D zsF;4i?}QKyc=py$`WHUki-?vH6}86J6t4~4^xl}SnIEorPP_299w7al5-_EuRbt~@*-eYl{Q)hHYw=E znf&MF-Rz2}O7nM%3z-P5Bbo40zCOdBHQoZONihUn;fU)kwSg9}yd zk>7ym;UGzyXp4t+8mdv`a#KTtmS|MgODeE76_9h8w(G;xxKc*iTW5QghZ{M%BeGWJ zT~2#dap=5gDRmgFH;b`e{mE>(IG<1O&c2)c9%tZMv6Wr^;KFQkl#(YgUFtaU;9+HW z8Y+gpor8rTb!LM88%bVs)$`;`_$j~p`d&I2t*I9p;0r&B_5r_o3nPqpr*2D2o!JSLLjdZZ6!0RE^ zbgoC4_XKP{VV|I`C#{$QnF}g=c+w3h`eqf^P+aehD4RKo2`G}x9&riz&*sDy3PkTB4U<~>iy39oXK4tx#vGm&hCCioz$geWl z^V4sK>6qAm_lKOgVt+eHy?+_y$HudteomD$j~n##@~m==(K};%^SrL^p%S0_74G{_qM()K&{+haa9XwG?Jr}=;q4?vV zWzQu|T$Z){4s44e<)E1U3Cos9ne6c>y}T9;-H*K{F5;fgg&LcXt5QA){oW z40gz8IahT$1X3=2g}b@)HHV1HVv}gF^iVC{cxRN#68BMnp;?!m)Saf+3}Y0%vTZmG z-83g`yQZthL~WWo??OFG{{37m&K^)pu9dsxOiwO70>OJ+pTgnt(;X1j+er~yLWI<2+TzW|9Bh$S z!t`Zrdn*A=>;D>RxbTyil!=R3)#WChGAMF_N39Zn?Oiz}t)j)|;zaeRp29_cW^Oy> zYk{Vw%}TUqAb&oBb7g0G6b|ek(NdR@?BXjvaZguPP!JA;JuRv?(345Pfu18h9_d(d zH%_Ut)wZlZ&SfUv&};c)W*N1}pm@AoQ1Hfwok`8I#Ayl%okf!(*AUJ zsO}EqaS|(2x77$e>KZbKcpZPW@MNX^$h+Jkr*-MYEc@ZBz(EiLC*dg1e*+DofW%T# zGk78Bb?QhNWIt(A<#RrA;UpzONKjB=wJ%#hmAbcwGFxmr)8qWb+4f!^ns!tz!Vu!7 z(TfTo7a)dPn+&Varj|Ne6mT|x?VmHVXMhZ5r3vlm@Si3%!-uWT0q^iVN9NNdf8#>k zZBd^;%gVjBssXiAw(GEr!=uZWFYojP2Tcyan}Vjy`~cGh70^=6@iD7F9yy`Kg;yU> z`&IwN%zIdj`)n*a4c!|1SNL;}m5noA&g36|J&$o4N{$aoSzK&Uq6b2z4GqOiAEdSk zR!oTq!R@L3GOmw(W!D(SXIqrqomi8Qlo=p-o>SGIsp$5dxQ>pT#&i6&1Nc$QTQXm$ zu;62bM((}0!p@e$8`Uvz?zFGzwEQ*l3sQBo*Gf1P)eQQecJ*kh%$fPV@1wx82C%}*xvt2~3GlF#Q*8)w}kpSRd7H@?xs zud+iUQhG4l3{*7d-YC}r=T2?hqi7WDRm#$&Ugp3q5Pox!lx;TFc;xRzGJS=IyHOBlO)FpS19)E7Lz{>X zHu7HQz_`=|@yr&bI@7=Nhl>UA3WW}h z=W13a+w&nC@C!9h_d(@hQxMmkQ9OH8P9Cspg>lZ;XwQY@JnNYLN*|#3e9c~36FepC z%3supV>?RS=7%B*9$|&8VCVnGFIg(EH?2^-_e>x!czL9Lecb4*N#&f3;}a?K)??X@ ztNp75#0-z~0+YZmh;cvB`%9KjfnrrG>udoh|4tjY<|@ut9*99rg{$o`B<-T_7nf~% z;y$zO;|)PPa`NPfVQ`5YS&8F8IY_F&S#s)1n{NiNO0>^llb0JS!Fk$_gRsQ(aC5e9ox$+4Wv)@q>GHRgIq zqRZ@tCO~?rl3{HfgUt%|cn$ga1Xc}E{ep+pZ;ogssc!=AN3Cp3kA!Hb-_oa4$b$(_ ziIS#MfO91TLPgl=rx7Mo0jYKWEF_M#P$O?a$1Tg48eUxX`1s&E@+zOxe3cpl1pi@4 z+}`>V?i<01Io1DCE@f(!>cr%}0HDsa5 z*1@P2B@(!$YzOBss=Z4jg7^hq^hSUmD_1Gmf^sk2<`lrJC)@f`I;{bS*8l@vMk@7i z=}C5i&j^Jx+=(+tc>!5-u1U&>gd-8vlo0Xlj#fKBT!dBPku9O%;37O77w6>pciZ-@ zeOZn^yO;u>%__mpO|M?D@H#JRRK5C$usC*bWS^8bWhOQ$8b$sVKlLX)$8FcTljE!g z-U!|NqriDDwv;{W$$6>-_^T^>xM4+jYv&P zoIhVaSi!EeR?gA_0i8bwxP|$pcI(u;$>-s~W_Y2zL%$&bOD(YgaD#mO-75?@TTW5k3oK+&B&K5C0R3aQPV+ zvEW9>y3Klh$JqnDR{Qf^W_mDJVL!>bOtyz5;ZaG5|u*I19l)0j(>5r2|UUi={n%9ojR*syrLPG zbT|19)Px#0Zq)1d$OAV4Jc``nd#IZrTo=En-pbxrhIy)&Un*gRSz%Z5Bor;r#O>pK z0!uQ~z@-Wvx=wnJV)69%n+3S)Cx_)+Zl#@b7^wv+P4ogRi9=%OnOv#M%1Y*~KQauI z2Bwqf1qA*{)z@t``&7BZ3tLX#iz>A4O^WZ6Bc^3nP`|tuM>;eBJlGy8L`) zli}J*FV6sq7zJs>W2kZ$pXZ!+ngrBj(>fXY;WL8BG4B#)E;%+$%hidSaJ#kzgGErk zF4PLJ%R!I|J@a6{tR*f(0caMHj5Q65sd~5=GVloTfqK9UrtQ;926in|Lwc~_qBSqF zfFmvjv+`UtA$YC+O~@o}7;V}7J6y&AFi3}oINqq+!speI3*@a{-iFLetTTe@Fa>$n z-W?~EQoNt4X=j@ESIv4_i90X*=E7uu`JrbY`|QbzDtK zlD4@TuC%$NwKyi)tVoIcYb&|Muy|Gm&e3WEGSj96)2(CVwYkuc2`p83>b=o#2diVU zpL{%>+aBl7d)~DAjYvkpci2@J>TLx4*phAEyeVhzi zDBPwB8OYBIQXG(>5W~I3qg;KLWFGwtJSvI*z9gd?A!G!Tj`toPPKyGmF9+Tp(90{p zv>AF&e)VG&-}wDJ*EfQ)vN;7|QGW4OF)$f&2`%sJ{Qvx(My?22o1@P$ziBHir=wImHetSD>7jg;GQ z<dB5)!KR z+Ac+ZlX^m8TWs1BbqJo04N?Tp&4iFCEG)*YxLtvEhh-6Bu>LD-QLCj1%?f{ZJ#Yd8 z3#;!re??Tc?=IpC?*1=W$TaFdgQjAqb+@w3mEh&Fg?ivU6kLC9XC<%9toFMKK*;{+ z9tszp0i{xf{3eCHXl+P{@yPX3Zhs&Et2a03Z-82w@b0zFe=?)A_FJV{jA;R;-wbUA z21F{MH%bnj1p&!rCR$;!Q36z=b+7~KLbVsjWwcSvmFYVV+k0J+GF=Sl8+dj{_`ij} zpZN{f1jhgdEvVu&S_+r8FAvdBgrVwolo{7ON6tS25p17a*utntV~mm%L&%MV*tBl6 zmHa_#%HIp*w(l;ycFIk__s9tdpq4vVfDBSVSc|Mx0$RKtGaiG6Nn!JTT%Y?r7e)C6 zs6gJ!I=PuGPiYTI^f_rQww3}mtH|22l`LiHqE+|)>sU(+LI9V}l`mpK`M}veG?~cSQHy=L(kEpvVQs>jBB>b_fy?`Qlm0f9p1e$vy=VnE5n``vngYa#>{34$D=9b$OfTICfQ@6>1?)bb7VI#cUFA`ZE#)oLjl4w`2=cRU0oa+;wcv! zfFL$o>~gcA#|+k{YKihd<7-l8ofRBBQhAi$Mse`Pa8HhV0w8oq!55wIF9FywUgyKt zQ2JvZ{(J_3`ti)u&Z#jLF==rLFSc@@vuEnp!|#Xu!v$bKWS#NnyK3apJsPgij;4s} z>Zm+w3_HhvNpWLNz+@BHsDgzuHE6ove({0~j9A&&=hU8DORm%s%+u@FuNRX_Ya(n* zy$5|+gXLx?;LzO*79G;`MTK0&t{_0d1ruLhuXdXe8c%aW?XB9iW$-SnRh4G0Q9K~# z@s=1@NSwkPVjJxR7?6rQV3{^T!Up~Zm-e7NRi_1DF@P@#L`@lM(u?$3k=e?;#2yOP zOI~0}fIG_6&7BIA8Yt*4hSdHalQx7({n~i5<~~m=2BDm{fZo0YV0@lEBIL#KCK~9gfXd6l_^(sSc%nMVNiAMQ0 z{jdyN0Qd8ImBN}q;CEYmP3a0bg3oo+Ejxc_@IjOL|D0&ChJ$SMh~^;1|LS?7TBbJ; zMwi1p0JfyNo?i0Lj#JVRiIw0ueb*eGN3^767ZT*_(EwnA z2SldiNd-z#6{h6mLFy&TMxS(i`X*|L}>~;WESVL|=$h58kKV#5aEsH!`Mf z6w+7tTV^mi1vKoQ2m`fyolLZqhFu%3P~pdFO`wiuLc`6^i;#7YTdpl08TlZ+qxBrz z9Nw`dC2k&`USpJ{_NnbY4ANu)`26ddkxd4|jJ3lYa+qE%D|7!hCD#9LE#ft#Yv-vB zfc_Z>1CaMg)Rt9`L6ZdWpL!L%S0Nv48q@wDhJDj~jyE3b2I?Y+zJBl-5cjZ#OWZ4Q z64NRZB{ut(4pp~Orn5B$%VF52fPg7j6~HPA{fY2j7VAyGb!SWrIi-{iypEQ-D5T4! ztQ4}i2L%`q*s*|I*kz0D8cLG316K7PPVF1X|1U5h#!}h;kxXTMI7>`6$K`Pd8Zvuc zi+%`lu=@SuFSrX?@`S9~XMJuqC2E1*ojWBrUeYi0t?K#_<(gk3_m?8qXMeKh<5PD^ zy}NDO_==;!3}TEIITI=w&(V*e4If2ZTQ4#DQ^AS^JKS^qF=2jK7z;oY;)|-)#%wWZ z05e=XT&;Ha+>k#)j6=S{P{Aduu!27TloM^Gm!Dm!FY(WS{TM2cmF^X+O(rwII|g&h z6lun@s8E3SW_zw7J2~?6xxeD3Q*WBY8y-1o;ke;RNb%DtAgL=**Fq}%yf`zw)&^DI zhlEINo}k}FFQy>v7~6HHv>i)ON=eCcrMB%GRfCLBP6g6lS86c5>2v?u(Ce0#&yo~C z^6QWcHRLgd78X--JhFluH;RZEU7#A20JQ-72#8*Z>(_ma(3^pqtC{m-5t+h*f|AxK z=Z~kgKVQV22Mcjycx2@M2qk`g$T2ry%d*cvLyLh+_j0tyED^#CB;inJKPbv!I*sGU z)5S)1KMRfXaE2bRwO95Gy6wzW5i(4?1;D3-zwzx%2!pri&6WO?RhzeGsYv@*`WI1$ zspO<62&KO7->)R+wMgRhDX<7O$wcuhuMc69-4|>4JeEG{^!T6SKQ@cYq)md0gtBPp zq1{hxk|IpB4Y#){JyfOv?;&x)0+-)@@`Qx*)Ta`qEYOKe13^ePa?*@%#e-l0)&0>6<^`ajQE6N6 z_9l5)ShPgP73^1ClfVn_1+m-E1?3w{zN+4_M?YN=7LdP$;nbcm>-#@kh6f1_E72{3r z1`d(OgmBK(`xZ3Q&HZEsP`7H_Xzb6!iv%OiGxxJV)u|FfY%@|Thlx$Mfp>#UwrAbJ z?Y$j7S*r%9CK=t(H~t6Z^6)af!U6OxmS-8D$^Gcl?=YFgmgT(r209*UGx2YyV^0fe%` zrSA;{Z(jVOFc}sN7)vqcW$mKxj~Ilz6QDu@FQMrMMG^6 zKNqI6TU=4A*psF+H(4U2%Iv{TG1w91Ixt_&Wt$JKu$Kv>B4V?adUDJRTq)>WA>@*E zuNk6b9|f|a7FNdeUGp5PZVMpggBGp>-ay<6z(}SoE9~FDA4HrSfRp#r$J3zL2bi4g zxxTPW21|3%;BPD6BjvxL!6Fj}$EnVP_c#q#79eb_r}giG&WIU!%|wd#y&vUfW7Bl* z&C^iL3fxDR{*?!OnPg*b+5vcs1wq~Myu(B*KUYRD-8B2K_+5)gtg+m~|DeB^(6=6w z{jvX3c7XqjVaYq%7AM#*@zy`8c?C`-+kxOpe_G0sf>+kZm)cuohTk~e_;8In987># z^{;C*CuCo_)w;i^3SxHoph%|EbnD=9oC({Rxd)CPD!2<|U%D6nw5j`fJp?(OQ?m+(vYec(&(LlUp?ibMS(u>p2 z*#`=N9WaM(pp(-eCp)(&qys(fT*I@PZ%dmdm9^lVXnwFh0o|7DHOs`Ip%XygvyP*` z*m;*$l>3;wRA1{tkem&4U|OqtHOsKFKyF@a)=Rn9PbngP4(8q51V{aG`nDbtAp9`_ zRz<%}5P%My38PhWi33=YA$CKDPN79-N@E3wL))7_#uK!tp~DZXi2=)hsJ#R&|uW{qo-Z`gawebG%(a*W#T zn9YKyPxSf6zZ%2K6y|=I3S8a8bIzm|_4+lJq{Vv}I&svfgr(hfdA4G#}3>Bubkw=A2^)8qp9z14)mIF zWtQ=C(@}aCFw@HrPY)Q^Oot$otr(D;znR;2BVBg(h9V}fOQ|t67kN& zF({H$d7PaXtE&%I7Zzv|f=e$J*lQyPhkAgO81uIBG?q^QK>2zRzsM*Y-mKK)wW?6T zBjK@wo!4m^Bixbd3c9fzpe$dgcmcNrL|OE$eSa-pDlhnT1Q?z}Vh;-JF8%9kSSQYz zUS;EzpZlaYd*)6;ZHc=h!F{~*jIadM>q1@Rkq|K;PHD6QL@ViDzfG<^dL9LU3vBv} z^ih)^!?8ePi5V0vO(w;(C)9n+ezLhfogEBs@uW+NX$=lM$b;QxMh4Jtuu5R34EhiL z^Gx@SrZTMjW~Hknqr1>XmXp)LN`ay-`t#?aCrzJsUi|WJRbo$?UhO|zfO=g%N9#GL z0(&o$xgSL+GK<_xW8nCgWuB=F0~phTUH=~pS;tS+e}xtK>6Dfbs8#^s_gPgyAov7+ z3dk-U9UVK7y@#K2;8X@DF-E`8fgh*${ZYW}U~By~)9Y&zb%4GQIZVcJ>`&xZe{_9( z&4hxS#S&mxyYOer!JWy(7fPSN*L~j8!>pM;b%BXVPgC6z`M`72;G`1vO8l|wh|^l{ z^=UbVi(XP@cdUvVC_aU6hpyZ{>uYPf#^!J9K!2T9qVSguA5IB)B`V)kQ&YQnlZ7zC zxJq4zgUZ6f!v1q&&z_yx*eB>2LZ`AHTGnYY86;fW_ci9!M7gW<|MTO?n>*Q&^XnBH>Tu%rKBFQ+|w>}qlH&%zJ_yPi4ymYJr{ zI^2C``r5a(kgUckgl(0~Q868Oxogocm~JX#!f&Y*^bs>EzKS<{(sTf~y>-+AcR%71 zJ73vAcVEigBuxz7TsdD@v0KYBIv1niX7_$*^wh5_=z*lbJJ$3{jT zG31~+Q!VjIj>cT+T0v5&F^8gLo=?u_jfYvDQ<=b65VOD)`|M=8nEw5095!(KZ5 zE;92u@L~rP*M2`YuJFUom9qfa%P_=}L3q3kZy1ylvHMxa>al>QgN{n302T*s`X%(C z17g?BG1ok(!LLFB+67Dp3g)e`cK2Z&+7aOK{AtAjYGlKUT?a18rO|g$G6!9Abbk-U zT4?CrYKQRvem`DC@3Jx0=I}Ke{AB@dDmE}|@8~b^tIY#>38Zutlzq!kA^^KgA<(F< zAk0HY(;X}2YtGOmK}9&FnVw~!DFdB(?JM^k5LVxVA%UpJBSsr~Ee;obh}@g=^Z?M1 zZnK5sfPhbKVx+1cC)rgFF}NgewH9$PnJ5R%UvoZ2H`4-|`QNrR(Jfxjd}lc5Gy$(hqKg zj@_886ZZ=uA3PIy(cEckHAkd)(RF|>=sVr-r@t2aoNafTV^>u038+^{P)?090@U1&)JxMA)*g z;)t6EFz@FM0>?s^o~`e14`3_?0qKHlcI=ZJ5W9)Mykf%ToTm=%pUNV^&=Oxx!^2_$ zUk8nqcb2NOK&eZCC+fep41WJtF4qRLS3wk8mZeAQtfmIq(N>IZ%cv!8=lVjaR3xpT z*sEH8NqzdRbmW>RZqvr%c4-&&xwyxPamU&07DXUp4=Z`c|K!mrM`3@ZAKU2EWW9i!SGzqNf;`#-1V-dD&59WZ>eD9nxGBN^I z{OON6hJ~>AD~xH>O(>I&j{d-7OvQ^PzQBwUT*jb#xq-@1qXIP>?>xBzh7hiy<>n|k{}YIw%_d`&^E_a*nZGMI zw?eUt4&?J5tn(??q=_-TJTo9F;nDsEgN8yv%b*?TyP#F7 zJt1>frdV&|Z^6zM5s@+^K(_^X<$!4krCz4~{HoCsX6hfd!eVT+5`Xah1SrJty3)Z4 z2Sw>2)a5B`fTcb1%JlN%I_@v{Li8IgX zW@&39=phRFhznc0jBAbFaL7*y?NXX3rM(cnP;Q)aDLg20=TD+-+2)}ygK1F^L#%%# zT%R~oqTV&d&7UEv`Q^`@iKhOThq62QNl!=|BFXQZM_`|Q=Q-jqmFEAzADFfhG>s|@ z&N?WifYd28cLc(zLIom~?BaTbV)h=Vu5ibNeR&dGi7gnH3Hh-wQ#vkvsQ0mDi_?0K zWIe72{i|q6CJfffb#a&e#rGkM?Zmg^g|V?+vl%Z;fC16LW8|IclNEi3Ize&l(w+5% zQQ#0@{oDp?d81a`CZJQBGtvV&h*{vR)T0_q1#r%0U4DjH4=>?y-{x0MYX;21(rFvx zN(!hYh#nGPU;GO~Yr3loc0^V;|EkF8dTN3c=cAT>@j~RwS&OHJMx@e(T#*%y?mbQcn_Eoi);y{ zTX*bv*@bnU0}KSPXc_b-Z?HvlCTopDK_8q~3yB2k=1nf}c!B%0j7IeU)#yCY`4+fz zVIIO@N4YPHilJw-%(#`+dxWB@Y=@_820#_UXGk~nUyUHu{X-PgvT;$}N^Wz%W6;!f zi27gvDlTsX9t~d^a6t9V;e8k}pXNLxhPAM_z>_U@oRv>$(l?{i*5d7hQTMsW!IiHr zkvL^>ANyZM?XI|Z?}V%#|8|?!*q;!i&}~;ZbIsdKfNnzE3c!3F)f?mPfhMP?pdHl4 zB0U!fRq|(N+o#=&VD?@FTLu#TAi77}h2BS_P-HZ9F^01Xbh~RWOQ3>Cw=&z=(hc4S zi10~?iGD7dC#}95~Ov0r)XIGjoEFVK+eBBo%@0- z1)ek;;Yh(Q0Kte!InK^JDIo!xK_`KsC}Co-FYS;q0bhu2mqs- z6hq=_yt%}kjaibZg%J%%#^J98Jy@+aDB{A?{pAw_SPwIvw;@Y1NKaMvj8U$7UeYHq zgQN62wc-TtqFH@f?Y?xDcws7O^hIw0blWOz%vC^Iys54pEp0y}7^?prbH0)exvXw^ zZk>2&^0O{V0;teT&{H4Kfgp5SFu>VfW*OZrSf^=m$T1AyJ#s(jkBMDU*d<_H7!d8P z>AwIRz(*Ju1g*43FI_rRT5-A#`IaADAL5x%Q2&7h{3iC82#h~m6QX;We{{WvzxnxW zJAX;`&d+~{{u{1Dywqr_=j+&01?Bltp8ge5^a(Fad7mOnU)VKA%J7$jT+;fDbP51L z(^f>XqhGw$6&cpp=iw4&iC@3Yd~Xor_q!ML+}h|2N=zrC4@h+QEIJO&%Sg}OZX>R)I{i=QO`QMLy7nC+P2PkxJkH znLqsFyglhAD4lY*8w+;MxOeX`Pr!~3?@3b;5ye56T8DVoMMUxq7z3X)NA9Cv(_7Q+ zw%eBkg5^=a|6HyfL=sFvD(iUPf1p6S6;V1jnE0)zI&0DjeHAlyw zlRo!_=~zu(HF3+L>vpG?*>WzPNiH++VGCKnD?X-ftOI4Ze-vJJLy%13tly;LbWjST ztQzTpC$lJpZ92-_0y-#kIrPKVK$U%%4Qx!=63x=trZukq>@=~9u}|Am0bqx0*}4N! zJU}YgtpNQJb7jRmnrVPR+|UP_4WJsd5|~9qdOhB&bEyzzs7XKhLed_QYoMembpv zei{^|Lo49qHt$~O0*fkij*!i*$)3v`IveBIRoQ-TiZy^}3j(zhQ0Wqh)&%UoK7?ib zC_hRJ+#lc@F%9Ju(Y?^M4%ER5cQ9li-ouog#(eKbEi7aC|3PK4jL~yLDm$UNvG7 zdM$3_Ir7e5@~Ol8v+b8T$>INS0W9ZjKe%V^7ksbc5-GV3F0RLEhZeyO_5j-LfNx)d zEEO(gI}49FW_jUQW&P7sDyJd zfllMPVBQKYHo&SP^ss~fX%)Did!0+!f885eN%_#+*hwz6&lk>ZYX#|G13HdOlGtP? zpqE|tswK-+aZ>MUDtTE0>^A*H=pKbV4JdbMXomXrmm~}rYmL26g9>*qJe^xcAxIlC zP+ZTD!t*}nc+YPMznvbiCqd}Ci?@M24X-mpCo`HJ$$tbT{D5{0(k-1?O^5U%~tp;JW@yQ<9X- z9XE@~eY$ubwrlxs5Z8u_Nmu<2dQ>El=PKYhk>5XIqkMou0(?SPTt9>9l0KoSvZyglv<5CE063Wuwz0N-LNfFBg`$R^T^%pw$29t z9S<}-Y&_I(APyS9NPEbzZ9KubfVjHbzEph@H*$e89nytkg`PhZ!WxgvLQQ35WsLVx z*9K83Mpuno*oJ7(J1nf_Ly*R#_{x`@qj$@5= zX9(}o&k9LOT7%DE-}W2JQ<6ezNBQU>*8Oc{0`|C>jgJBx_!7vjr4VC||{NZ1%gnwr!W&QgMF6)1$ zxe)AjXdqS@iC!)&eV=j#O>XA*M2W6uZoOt{n5@W@;&Jj&4gCu7D?4MmbzM#!kW^BT zH6fkk^F2oCa{Pi~{=SH4fR5kpALy+mfR~`AT*f9crHwWn4bfB)JR>sy7XY>I{{Vby`BaG zxYJCJXe5k%uB~9tU!N_02Wp(yo9ox>`b{hxh@TCDrH>Ud6dtSK-H({OrZF|Xo8Uf2 ze7KzYc9&}7rMMk|zc2*b5@>Z+U=RERHeNkj>;bMkNV_2RE9Y zLuo*I!i-F<#9O=kA*pf6I$g8EgN?5Ma`j6$)YGxK(3BWwhi@Z%33ART*xP`L zvuuFwWHuTDl-6-S1Q}{S&~*aEqg*br&jgm9Mi^o41!Na-JNdz5Ov_d{>$-CZdBPG+PIV2 zk&$e9kKN$HaP6I9UPFt}z1P97Ey+Nh*4s0;)j+kk4{DY&S#UmQMcI`Hfbi3Us`?xf zg5w3>u^q%N%nWofRCP()>JmzgU~F<{p*fIbZg3Fo%wWu6jJ)(>LJ5_#c$>V9?cu;@D{Jo3^XuGAGX?<9OaGnj z1J#=`gn3@iIV#>5#LyjV+@A0}&})Ot;if{j4wuP#IfJJlkV{IeOAAEL$d2}tFfbOJ z-O%Z$hMz5^L_cY=*;s0y-8X;1W-@Z64DC8>ldF^VfP+mbQXxt`M+w?VpFw;u=l znu2qk4q8o5C($(1!+TcG_Gh%(X}+cIlIuq_uQKp^?{56=34j$aXUHi@oo9^N0=$7D z`P)qx67ii4i0PSu^j;_&5n%&5wO+WP`U-Y|Tvg}N3^Xr~=N!K;OQwNaZ@OMEYy%N^ zzkreuOCB`1s8$lZ+R05uxf`UFmQ8P6Su=;ILs+&#r>Cf%FP$PuXJTl?dS8*QwCDmW zLwJ0%AMW1Tq?_qZ?nN#O;>h01<3M(aS&k>cq|u&S3Tl19IzJaR7VZK(Gt?q@0Kc;( zi$O;uo;;EpcWlW86vv!VM)ljuo@S3TNC#u_mfesxIb_p!dU#bX!$c03=;moAcO5)XHjjtF7ul15Z+-hy8) z^k+gLrM6!=+u1kkz9C(kklP_Bjr^GD|APMaf2HGRoXR9<;W{b_qc%>L7^0z~S3v{s z@8^+<-GFXVV70pv zYmnUwTmR5eAZ}L)v>(@nqe=pPLc>Pj3x?TOW&8JSNE5MGVZ!yUXvSt(0!CHJW9AB{ z0RnISl*xwS4_n#rWh(xz7tf7>Kco-LhK%G*y9=o+TEU|u#h}=t69OZQ3o-xUL**BT z4n^$h01$`(ZvuFDVRj3+(sl&`M4UzpB5gxsc0gZzj~mZvS0_Tp3=H%Ds=gawDP|B$ zURs}8LoHv1&hX=4KpO*u2OMbuU@Ddn9ngy#wLm~%SDOBnYne}vzdmOmp&{PfI2AvH zmcvwlX7^gGXrx`EnDg|~YR##;CzHYUwQCoe&u_W_l5L!QuXXxZb3`w6j{^js1S|^_ z?Pi~&xcB@hCscuLFjIx#L3$2I!5!=IQQRo*ew#_0Jxqmyr27JVC|x;|A3IY?u86TV zMoFphfI6U3J7QNp1L-}|gh%sM2EC*idNuH9jo}qH$hR|aw_aq=Bkw2Fj4lFQW^al+ z3j99MgV0o61xbEmMb8!_l!a2tY!pmhh8*=BW0|U*deLd(Ef9p>v`tsIwn3-4o_un(i-lMcVp+(}+UBJae9b z%HLKxS8HU!J5*xcM(724@fSQsu80I%LS~Rc-fXZ^kPSfg);IyAd64mj0!6-w#KO21 z&oYnI7Wi==h&GR*2z-DvO`e@b<}AJC^snXxMsaWyLXH5;F&TP2fS3W(l7M-DLJp6g zfpSb1cwSXL>jQZZ?~)#5b17}+c+dm-kE;heI9h*#1zp;@rvt{LxK)g{0EA}yEM<$# z&q9cB$ChA7Cu za7O~A3>&7=tNlTU6H(s1hf2ZitXl@*Y6*I#)FW1i&`mHo|8zB4L8%uHe0=IMOrVnV z-besT;=OOT2LTqmSyo!rF9vqc697(x*Y@K`@cO~_*z!>#JSf^dX|AD3Dk%(BPPq@1tV5H1PoJme%V?d9TQC=AK2bP9IrZQBgLd1oPDIvT^kVB`d2QD8nPapO zJZg^T`H`<++Frbknf`~~GylgYh5Rd0ChW{hY-bB8$?JBypv|0S4L(I#|Ml0yhVr zyxSZEE)}_H*d{$$kE5}Jeor9pcUA^yA+5I1fhp2;Bv|Nvh=#sjeRA2h%IXMUOH#B zrz8HO0h<+LtM=wS)7eUfx&#b|o&Bx^3OtKFM=xZV*02#g+r^iJg@p2ekx0FlzcjrL z9NPNWA)rg(+MyK`Tq$ei0PB3e$u7Bqp|e(iMzeO_BzyIP%`*<;+5H_t1)wAQ**+OY zfl&*@oC>|6nMV(fv1qMD+(cr*5VYAWXUpf@@eUOJCPc9DPO5+u z#X$y6g#Ut5_sZ1E{DXY9fEN7i41-YUj8{i-v@10@6UE3F#_W}G*RkhV8TI|m^; z3;3JMc-PqtTUGR8QoQcKn-|t2*s+9#RPQ72Yf)hbdfyWv>r!mg3 z9G$?B36iQkNH|w2n?$uxd>`&i;(vKmvfVt9k=`1`n;srsH1X4@G&~|Nt;I+y_++kS z`ki8|l;y3S&r3H?^IVX#o(%h%%_zBh@BR2=0^I2UQJCQ}8mHHnaYnm=b@}pVz^((; z{!C<0&gK@0`Jjot7eLzJ0*nOMC}$A|0~mhE0DKy4iA|>b9msGjaDB_! z4s5)1E3(xsTTlH&>!%hHG;WUH%4q+B;|~>6)6mO7jeZziL>m;^RekO}5ZXjs#C1fy zf0bND=Uld5{^_x65ay-2!?-(d>N+QEcXc&2P%1CMmOkz>1@rN&ad4i167Bq>cJM3O zpgKSDhegBl>V=2|G0yh|8ItwHz-9>2YS^9+Qy;ouCHz{O4}q8n{b`QFflbF3^!|6N zmIwoO9QdG#;(*z+3LA zOV!B;O3@A)vY1MnD8j{W-2QjZ?LjyT4^-tT7@5#})+;D#_a(WSs$vIpgh&wcu`luNFmk%kg-PB2j=TzD{_n-khJoUOKZ;X^0iCL zHP5~+Q`(*~tB!ZVf!M8DX6flA#xoMg?^uOwYqc`qKl6zbVY_|=UE0NHgZkeZ@^$T1 zom@FYb&%_`6ae2I26@I(3`s%jmByl`3n7zGc>bBA5E(UJmQ_R&Y1%tE}nSQ*?ij zkx6v(;+SMHcjtEwor-gN_phI!I0s~}m8=ILYwSl?j&-LG-R1DG`2T%I*-5u8OWu@w zg!uZ|w!9?$@b9YwT`FJhpS>O5|3V+W@}>)Eah z=e2#S{VwC@U;-<0wM=-!n|6` z@?UJRmOL(%wx+^7I;&x;MrgB@1S1N1rApC5hhU_ zp)n|zsakvEjqG5>@b{725phuC49F@iZD;h-X|Hey0DD5$8Y2q-8~KqY4c$+jXW*@zNFlqet~ zIh2AVm7I#41qzA+fg%;utX*`UJ9F>M_k8y}GtbQZuLEM$-oNm^>s`T)ajl|v&^CtA z(AC%Iu=ny_JC0dKLQjCq53+=U*XK!pae8SX2cNVR8DGTjJTItCJxYZFc@pk6#d~5b zW?$Z0U*zMJ!;~^{8DM4>I_F$!Uz~FOUb@l>1mT{reU~k4E9aj?pBowdoWtHI6+0fn zBhM6+b|ylhsxpVV*z<=QMfdE98`lh@MBJ`9EG#p{NT3Rvx|DrWlHC&0b-yGce}Sa# zFf=phW0~vZ@T~=w991=M6%8vGtvyNsT;n~5g=P6(cj@riw>i*EglPFa6<##S)CFTI zuj`@JrgJspDUKtKy`RfeV>a)}rN{5Mzsf6Il@hjf#}Dk=*0vviT9Nyx7gDY{8B}sh zjeXh~q-{60p;FrRTU!R-rKp=FbW7HXV_SAr<$@R9TE+h&n-Hp9hCO8 zZ*NJwRqhj?BCi@+FdK#f(wrq4WN0;@_UTN_MYwy=tJ8+Ku?DIJ8irDr+#|v6b9u%p zugg>9!{g048twGjFDuqCYj;UY&xcKQ@YK7X9tzP6yHy?NCp}(p(ud=n^(UnbyK@`5 z5=XyxaBP44Jbf=~N8#R)cB~fr+CeLQ z{q9J1o|=WkMsQO()Dt!89X^TrF{hFW@Tqe6T*(WA{l%-f+J_Q^B^-t%Ouh%OcGR)s zYMr`rTUR;WyON(9d8MeIwE2$*=7l6?QrkD-?{lVZDk_naNg80FH>^6$x$o&dS*NN| zK|YgI)i{+77s*i{Xxu|CiN#qx0>k;;m6uJa`hDK(ixfSsIc=z9oGNkfml`CmJtHbL zb$6XByUY|>^`C#O`Y}t)xaCgYR#*^|_^3-AZK#WgIXU!mpo(;TuqJS~S87b1`6TkA8)Xx}qPg~tKn!DGS^UbM8wN}MFSgb2{r|Atk_pK9& z$_A&Bw^${|=+CT7?f;$?e=;>tmBgq^g^^32Yk+jF(O5U@l!A|o%+dkt9`}`VKEg&v zu9d#}Q=T+G)2J(v&u~g`rZG&r?#A$%+4kyr(QK#xQu|VWEy-LVE0X`J3wxMH(oL&DvE3!3aFvpjEzLYp zcCLHevpFl^u?te%$1-&-d_ZxNO*fH_BMEj6Z-p`5<5@U8qRN6_`itcz- z*s+f)I^xcFlpsv{nUl;eVr*BZ(T4kHd~X-S?-k@qAAIRCk}8D}@`lN!Ap0=HWo>#?`|`Xfy- zQ^hwm(_I|NAEeVBo-NNh8*y)D)xx5KUHYmP!xjGA+39`fpG0499UL^2B-O`JMx2ji zc0a~R;K#aDN;z9>S8$L6*K-s9`u-MNMu)5R{l)s``@6YL!9BSxp?2p3!H$E(&yj=E z-?BNK)cAF*SCVxLYStdzcr5v9*4~}ww|*Ualp-PRQo=$5u9-Hao8bRstNeCe%7a!P zT(ocTzwbNioi4C#(6nZYkkTJ&Vz_BN-pH-%y;@9}@O_rh@OwV1meXuY-vka};*(dG zSjWz>B^l<=I*E_K_WyP9{wEzqJDKF1@!Jvc^X{DywxI?Ro~5^wZz_9M9lO+;;CS@S zif7R+uQqZW33}sk_QqM|n>E+szn}Dc`u*^puNzmq^y<)esHC+TJeZzXQ`v7IOE;iS zfw(>|-apxPG5}WLnQ~jd zyQ5Fo7P#D|{aRw$2c`5-4eGPLwY!0r4%<9@wxP;3AN1z;bA?wZVMm##JGU^$cPZAY zB54xr)Jt(1LMD7*A_Lt#b7n^KOAh93n9(&oSho}Gv9RbD8^cF^4_ErK9y7y_XSbr& zJMEnG+bx{>sefYuW2zml8LGodajJCG|a*;E~9E(kuj1DDZ@V9XgTRmR^ufyAmrkS$7!B zJ7PEij^gdE`&&-7d2fOC^{Jpu_a;CV%ZF-?PZO(B>rc)(PfUjt6 z(wGl}b#-V6FZgqd6Z2lr)!XdnPjqeOU(1}RRr+ns?7J&t-Jtr~um%X7RgX4G4tw}! zf=JYyVY#IloZ4F;NY;i^J4m__GBmH^*;_+E8+!tm6I?_%F73JasuTYB^3q2N^0jl0 zqM2Rg2OmrL3-F`{fTTNA@BHfcJ@&%oU860Qf}peqZ9!=R%ES8@!9AA-UI3zp<=hAw z{{HVT$AOZgg*)OqjuCZ3lJ?=1IZ%EtP&1xXN+e*;X;7o>2BT$H&=IiQIjG7z6?AOR z`$eDE{p*G7;E32(6?gXO@8V7qLCVg^cR~Mnxj7Y(@B=PlN;=1w8K>F@667}fZ$Xv{ z5ildzgYl-1uuK4Ds3CE?>_S5Ag?*b^Qt=}$^9UDoJ=&Yq&lTaIQxqtp&~v>!IPL7S zc)#tkeCeKR_*U}Y0!h>%j{yLH_wY@-@UQ~G?7ruk^0#@2?uAY41h>WER~rDvZrC6< z5~^{g<%08zr0|M#^TC`O<-s4!Thj6Jqv=;kZmu7HElE;()EuuyrNCM0Cx~}6xZDla z#^^e&|qm_U1bdiMrhLun~KJ zL%JW0szDTguHiUdezZ|bReq7G$Gw-MOn}EBRmlE>; zDzGX-@T}HTI$TAW_;c~9{SBZ|->-rg&skv}X2;D@3R7)d3rdKCNL#{(#(#Qpgi8V4|7`Bt+4*SPfJdpDYHLaai={8 zoC?>@PfFjONzU;xr%OZ{>p&t*z_-g5-U5%Y5zgBFYu}!i=YXdkCO(%0k5zz=@K`;l zJ=f`MkNpKpw*v)^89ic=7+A`160r4&+QqCfsO!zz!iCP#}|n z#ld}60mbIOYn%QUgx-mKt{;`}uk6RgIzw-vO+#LRBU2~e<$j6*$-8Jh;A@_Hqy#C) zpD-J%8vj=-&_zurIYu1zESYf^5m1Q24j(I7VIszYI;8ur4n!>ZsMvI${ zAZgBnc37Ho2vkM@=r%gebLXj%!{*K3aSP+U3U4;V-E|v28pO>^UXUFBo(ed$eJLMn zNYi<7V-TB!0-YOk`7_e1x7m?#RUDS!#-SeZVu@?J*>Fr6GR|l2_b^i{2{w}r>)-5i!5uOL(2f9MOKC4uc22(+YW#e~P{lDhm!#TidVa*}nLt?#NT2{ojf&%xZ4W9w)ca7}ee z$!bom1T`uigp}`QUfN^D{SSG@3Mw~M>)JHV{`sztRV#nd)cR!rzdsRNhzOTMFpuUn zuI_#Yvh57;T39Wt_#jF42!Q@b5%w`xh$s+j1=yIR$wkP9# z-#Xrut-=j#+>(AiHg{C6HpDXNu+=pthR`{vlRU4B2j6w=@e_$~rDwtB0MwOA95)&n z#?COh@^nJ|Di_Lgw}KcIj}`U9c>7k=seqHBNK4Q?dp5mldUj|Gb>b%T1caZ&M%lpJ zigD2$)dp;zgCUYTVl+yeq9{jgf9K#9yN2Z<7d5!*{3+k9&+S9+E?b3p4i&z2a4&lf zk9Vh^WihJil+p-UcWSd}f7z1^)foRsTMS4F`n~a_0yYmG8n7bgIQ-S&Fv0|iy049P ze!fL%h378(s+_M)2G{f7G;e40kt_Bjz%DXLIm*dQ_P(zeDp_b5aSFv{*XahKqIqZ0UAlEWkTC*fP~)b@{<#d1pvK2>&*CJ#P9iY=xeYAV6Pu zF?!x;%N~_CP`M3SVB}7IfBzJS)gUIMfDfe)C3zR@Kn-=>^AIp_SWZ&P5aeI^=R6kG zC=|oQjgzS@88JLDH_My(*O0os6}JetuPgDIVEoBW$uMoSM@`gag;~$!knCD66#j(s zE`;t-`o*N|yh6#@hsf%|9gNFSjuUfpimdZxRNY&Vji=@1arQxPcZvP0Uz(B8Fi2`k zLp}g;jV+}MTA8R*24ZF`}4s`oC%pF*^a-&f_rTq9knN^Msm#*f!IAT-76W0clwdeaB?6VI#fXx&a zsHQMzYgSUjEibR7lQ~+ZTp;84^GluK18S%!k7W0}sKdg1+q1=R3b9>~!M0PobB%in zjP}}@MI?e*hr_nWC+M`guv#v;^Y}d#PTYi>MGjpj&t%nnmuz3?P<7~VtwcK}j>irq zYWDdMQO%FH1*mu8cD@No4c!Y&@z#(%>`5)FIzQLx!>JIu`aLIV4&OY7m9>CH%GZ(r zvmWU2-teBH;_Nx)rJ1qt`7rm(nwwRBe==?co0HPM@#qSTHHPvL^W|%a0m5YcWysbA zHFoU8a3N>>N7;5tj(s>>{7zf$Q)3{b&z+Y8twe9#v!_^ZB37MuVBRVH5#F+2$Zk%M zd4XRHIea|9BvyWV?9X4|3d`($65wU%L%m{!P`rd#8zRg&uof`p_eZw%hu$v` zsnW?kkQs!-Q--{d*?D&roK3n-UYozHHUsaIrpbV$k9Z3G2X`$oU;=v?tPiwxqC6tkbl=f z`->-QLmecKPr3(PG~%5dwtqbl?(u7uTH<#3Y3Fj0#$41=hN0Fs(P8kqWp;(n%Kj{s z$L(c;;~U*H11G=s2fH(uENgmaqWr%S=B%IZd7T`On$oV1ug9ZBtLyGCP<5~w2{~Wa za?8&2ZXoptHUmrv$oAQ60V$!IRfMP z44c%zLuh6uAq3))nr4!cMxnR$=DCD46SNK%N{PB8HzoD^YZuEDs}~Y44!<&x>=&Wk zIAxoi>P&OF<1bCmM7J7m)?~x)ge61=L+6lDmEl1$`%RWJ%%?vUQHlmGH4!XvBy3TlDwahUg4SJ6&lE6x4|d=fmh3_oKcZ+nz!V0rQyO(pQ=C{8&1FxR5I4Iyh#{;q~q9MT*qQ{jFXC1 zX6?B+FWh|7jl3sxKy%jbDxk^E#;T*9WsU{NEf&EX$Jrf!n}Eo#qI8Mf=?LOD=W5BYRMJFGxyPB# zox-zZ;)g8v8@KsWAYa8E`_ml^>?@0HtknbJ4+ZU~y>VTkXX4uQK>)MfVi}H~_38$@ z&j({0u5x2o>#=Z@JMy)<6YC3L;uRH8u^|m2{>D1TD%7~X1je9Aa?`%VEn@Nonz_Y( zjr;4uYqnYVCSz`09^3Y&>>qc+tGw||<2x$mXsrf<+bzN;#S@Fs_=U&zhHCkSQ%fMe~=I{M#}&ooqrLTx(dAr!AL{%WcXBttmqs-|>{Z_&Cq)8(}ty>}X1w}Z57jEC1M|FbR8 zqqX7g)5Z;@>A661An#pq z)iIL+bgw>ZGQCa@SyJsuZJMB#pq-fz%BXwzxX*~3TDiX?`h1QR1)M^pT<{pk0KJ_Y z5?$@LqT@m~E#E0}9R&h3=$v2H##B1ZPl^JPSm({>-kJ<5Ro~Yzp5Njwc7+1+SiSw| zj!Ax^)f#DYK9x!W4dZTXW{f27&4M67Dv~LkQ{|vtv(kl%t$xo@xDZ7-|3^qk+)H?vS3er*wWKHR zyF9BtN4NAkF%4qKEG!GR%TBp$GzY5u%C5@}q!yK59t5dL=urQ60vH=KXXsR@m_X?^ydudGqc9a5@T z1^;~KJ(-l-!P3t5WDrR7hsg)wY0U)Y492aX{EgDU&$=!L<4^ewX=J!Xp<%!`&SiBB zI@}k8wA0OcJpJ6oeol|+=1uF@R*9ixi&rPXWK)$m00ECpp=!Z)k+0Ltp_f10wjR9X zEbIcnIX^0OJAo??qx>$uOSRUz&SC|NqUxD9~VX$ZILlRFL!XIOUdUTCxV zR-T~F%tmKg1;AMAWB8cOo93hY~}#3kzA(`uTJ}X^{^q7rWhPpAhxR{kiQT; zaeJn<=*XZyQC{-+7j(>wl|-zLn@3NAOuVJUv9nOzz4aJrT0a$px|n@PP*ea1&0+Z3 zgC8=&y7{>{TCnIb!tkR&89onMDZ++$nsFQii`$-hD#Omx;pnV;isf`s4E2Dh85vH{ zM&$REur4}c)-L4;;BEb_1T1GX83KZW3SNK?eOV0-U{UnS8K&Hfo&X<&W_-Z05e{if z*H0`xYM-OrF74MRPz6%A*7TDrnmTqWxVfPfP?a41#>2TZZqODb?bMXObK+}!(iQe! zLL|}z328o0$^>kYa&K2}1wRi8C;KcLL$AWB3(}jKQH`zfLlg3GQu@r4#V4c3KXrg| zucyQF!JET*lCrHOg{zph%E_!P+nmv9NQ9 zIkl94EHo;ebVqJ)Jsl#$I>ztFALm{=0EXE=HjBal8Q&4Ncpj=stO>8qNo3aeK7U>j zE?rV4xMi?PuSBKvudZY5BrwDM+-gZKZUf>j)9(or5$?#Vi#_&AiV6TNROKCLyH^)I7En@b6l}X3a?~8} z>&Ld3h?g2G`0SxzuWk$Y^{=LDW6_v^hj2dG3?ibzbkPp84Rfk!dv60#(89z)(;}`m zzJ7b2Qy#OnJ7R=HvJgwVSx$k0c?T-=%kgUaRDVpUCF*b%<-5xIQ$6$94|XsB%8$XPe`NkK zBrzVY;9C=8ETMVAZU@+epwu`d6v55rIPLGRiqOJUv^FXxFV}f02|pUIOF9ldIFv@p zO&|K?1nj>+r8;MSK7x~RnYB!gX%$)j29s+)$p?y7Z{7@Faha)C*Cb4qy1!UTI=CeR z`lvqfgY54x(bo8(FF`nu{0BtH4ewqOD(fRzxBqHOaNX)-X<&aY5S`w_?I^Op$iDQ2 z{v^o|QtQvYA40``JT39{rr3>bQ(iBR7! zRY-1yFyag*t9Oz?T+h$2Z}YwLt>(9 zjQj9NcQxX0I&bWd%u-*y9cFwe6J`l@Gn=XL;vga>dFW)=G2HQz)+N(rby_SDT3 z{E;T=-3na4+Q1}yZ}0v082RR)Z75dMV*$|VsGVNU0~4Wjl4QB`9K@hcV^HCsDH}K; zPOhcWuj9MNQEy37(_4Z?5~hyaT?_~pyTr}dR>iO7zgvt}R57`M4ac%*YQgx|K1X z&zs8jbRxr9LBin2aK7stA2Nji(>nghvg^^Zt1ePzzW3vmw!l0pK&s|nw_GlCp7p0 z-CoxtyfObUa2>lAprWku{8I<{Gv_PS+I~2oDLk}|x7zBRA{%lX{%bQeio$cfPyPgG zdo|5uaOnV$Ux;2{4YtL@ZhEp&a}ykXLHBj$vl`5KUA*mYETBf9>oEqKX%_RvsLc1N zCvn#kX~CEuz|+PVhX|Z_T4SL$_;LV&JD25qa>w_2>Z3%4Fw7Ls3F@nS5Cf`zr5w6( zfs?1emOdnk6e}J+Sp|P?;?y1{k43g;j*UYdR;^te5CH=t0_!~?*R1WXOPx;F|LNxoNnG0S*R&u zqBVzCp&&}s{Qm}6qcPOTu-LMH_2gPxhedqbq&>F@G;ijyJofEJUBv39>`Hc?nEr9% zKa_*_q`d5CgSNZAzLKwe5B~Up^hzY39Ytk{*22r~Hnmx#K0)`eUV&(wAqFuo&^usH zbr&htB}{$7c_@D_cWMbRws>H7d*Gm=u4Uav=zrh=e$l1#&si+B>Q|rdMYdtOtm`ID z$MgdOAWx#80-!omCb$$MqD>d1C#rV-uPVhOHllgb(qQW6`Fd{W`f~p&Hp{O~qknoK7c9*$@w-w2K74 zv>xd8Jhw`)-aObXhkUkr+?hry*hqDhGoC>~7n*a;RJBB46efVjl)c=UIX`n9SG}gg z+}0wqYZlcw)%82Zt4ijw)7SE#58QR|U<&vjUGGo&sJ|v$dsc0cacneIe75(Qs8Tyb zEGN7+?G4>wHK9`_H|KL?PIjYz=6(F0S19<*#A(Fa60faDd)d z2xxu!`9R16qvZzhcW=MhzgtVIkB@Pzz-0gVo91Pp_rkiW%W-v;T&ALSnkh{})) zhDadf_vPpSi8$MA0Y#oKHS|6YPxQ@>xVG2*FELPif6~Dh1Z{k9&=HLT>_f|O)X zZS>i9U(ZC^9;|9N02Q9KB1b7?BqS%f2{YK zgC3Io3+kU4EtCOC#jWpIBmB&7p)$=KJ2eD(EOm~D zQxP3YN7CT9o9lgI1>7OE;|Mn}J~UwWTFS}2w*M8ZcR;DFR{TYEk~(FLdK~5}U&%{W zHH{35rvlIj#D*qhA2=^ir9rr5fS#-zH%$Kc1ut#kzp6J!fcl&~5)3r;3q)%x;&i>y z0*zHZCeugFn;Bq~`EEUU=u2x?JdEDWg*gwS;mx5fD1orXzIys2l(%v}pn&zG&-;75 zT`zEO8C`4n_>aY{dG<((4*8o=$-E*#9_2keps(M{9Te8kBqyl!So;8h3XNs~Sps*$+Ii zx0%QbpA|+(3STG{=QlmY@)s2;+}-b^YXN0HJ>`t zB(CAIlRnq7Tp@;c#0LdVgxFXMA|I0Q`wKiQiMz#Vas*~{95JYDtSY6aPPL&0!&Ur+ zOC)Ix6_u(%Yi2So9AAu_kljc{yGaaSDVz6ap(2G3o&?whe=e0xB+l3EH!8!UjBA5% z1R!*N0M`(@f01}#<1)Th7-bg-L^4bGrdBO+A|Qj7%LGA`Q_6jTRR;t#C26;S^V5eQ zr98&ZeXmt9DzE!uJJ zoz@J4yl(gG%C{EU*|}T1&z!M#xxbs(|5lwGv#SSwL!}GS$CzoP+_I=laWmr>DbUmO zNjHxX?;7e<05P1*@d)N>FQgEy(3?QJCNBxEArwEaEmo{}2z;&*Ac_%YUWw4r!(nE) zF&P5~`)uH5a>F6uH4Qu_6xT2iBMhh@pn`cVNPc^Z?5_uxS?1Mu5mdbPycTx8i8!@H zr=bS(C`H_vms9lLuH8YJRLemri^sJ)+n_dD7;H348Yi!q<@ig3Rr@c#I@VvI zEq`$VKndmv6A00G@ZrZO88@6J_;mAAjXWYIy&${F&JF)GX3v_X>?Pa;@E&0jQ$>Cx zIH`FFMp_za7T$-9h$quY8@^V-e_mT}XWHZD_FKmOb&B+{%O0Q+1iyFz52z`b(NFiV z`3SSa(x-S_xl;)R0&pVx3VPkfX0!?@Jm111<~;a;+*ntX^cD&#lef6Qh}Q!GBRc1C zd`DRPID(-uhZq#O2>8u>G?^?0IdzuavLYo+)dJgy=*}ah4T>j5d-WLj`-x8N=ERDL$s_T~grH@HXX3Th8qXl3Y4H;4-eD-dBW ztxTuz!vh>j z@@xdtqg8=#e!TKqlxA=FlML&g-9j3<>(f_msvzddm_%a+p9Ab1OxuqbYuzl@z{KXf zUn5SrrYMEvs(xVY{yd*mYWt6xYb=6bq&(7&JO1qwTZNW}nKTa8%<1EaBP{`j%py8& zGjBmZA}Bnyw@zy-iP!%qCzWIp_01g0yO;!;nWZ-cUO{GU>9@e&P?px{hD}LF(4Xz; z=9E}63)!{i4x!Wcqp@~`v@GF zPwEJ&`puFmXCer|yfe`Dz|sNfJdFeKG5g^A<zyXJu{dj1h^~K8ccGJ`H8{W*M)%TPxu91^|HSdA?2u|;`s*rtG9W( zHcm}k%lXlkGl{7MjFU(Vn@dNU37vOfbLLp8o-?vyLyo!u<UIc=bcC481g&`3otfK%FA5taiM z`AMH}8(0WoK=Mj8#zB4_c~rbd%}(520JnN~t8{NQE+=14?A%858TEWqk7_&uN4gqV|10T#F zApH+nAlYFkRG;VEcu_0$=B@HzQ3P=(RA^@xr=q{Yo=<3dX&h zI`a9v&M{I-!j~U+yj=>jzv%6@==s1?s*0<1Mxzaj6xmIZkDvbj$Sv_%*iiQ0$e($H zS|Hg0&(EUiLy^wozCamF9tG14?pjUC9=s<41pp2@tq<4FOe}o*2+Vh*P*W%cJYzHR zXjhN_zKz{9fJj8*dR&a#bXQ5EuH_{Dr4JYEuT?qzL^?sB1?}5DcFeDcvu~|H30;*y z50}Q|oJ8CR$T0Amg<`p3D^mfkA80!!Sa6aRn~KT@p6}bLs=K$NoC?_SBh1Ilmp8SL zcHDM;cFk-3>@Dj@a@Kx>wUtpuOwHR$RaDTLQwJw1HXYUQIN;PTxnlbp`)S(^5zJ8FM?zOd+bop8MsgrA zJ{)4zCC6I1dj-VwnPJnRN$W*&Mf~OOE*8$6pWeQ?jwaeY>^6-w>e^NJt zBj+C|zKA>RztgzHE$Pt z+B=1H$044rk0&OxHJea)-bMG0lqI$7S%^vS-nss&v+dB6gS6`98YxGrL=9135A zmT%)}h*fs|{-Rph8N&x-!L!Ur*is;7+`!1=59iN!X${G`d_MOuv!#z$%3>h(M>-P> zZl8^N&=qyVfH8XW_>b}+sL|0KdVF+M+5%GDB(ko+4PFLs4NX?>-DzcA`fkZQs#o?k zT%K!u z$^4Z7!yly2OH6vFw zVE6&dZ=N7(+xy1XP+keIvAN0Z2T=Qx7mQlc=fS`{CylJ_fSRNr!UJLSBk--2bGXvJ zoW|UVVw|yGyB#FC@!n3794oFs>;Z?3hbY_@$Q3j3#y;5i-qCww5){Iip*Su*=aE2P zD1(v|kgF`tdEf$w!X_dCn?IV1x{%+aGx2ycjrlB&Wm7!5knb;3FU3zJgW!l8Lt$XU zej=#>r%oj}d|;G}Pd4_{`s=E09w9%zXC0Xwjf;sG>`11Kb`@IWXI&_{K+|z5 zJBfGva7;HY!3(*%(jWqDJT&k=fHhZlHvkmMd*BuG{uVVEN~~7gGt4}|FW-@Fz+v+c z{Iuu>V&vQQTc-0PVCRATy9EU?QGTtH$BwfP%~0q-9gJQnby?yjjR{ko?_Q?DT@}oj z3_7^dz^bR()RV!rlV!SmLCW)X352*deRJ2zHyiwb5^Tj1JF?epCrD0=X_x;eqvU_| zhV$R?udt`orCd&Ew4VzMkZJziEM4ZQW;#T2+Gi`8m&y;k{LB2g1{+MFu+TJr@m+E;Lr>2s?ZJKBLTc1=n#pTjWBH< zf2OVxodbH}+n+zmS~9Jl3>?t%NHkDac(JzK9RocBjM=P9D1 zMNtU*Jhzqn&c4iN!7>@fwX>Cp-7F#|QgqY={uh5-#9b_Hr!zV$O zb`4%4?nSsv|r=xS)|hQoSO5;K${CjvZu)UagOkIlp6G;0;EchXCFpW` z9^}tfpOgAv%ziEf~SJD^}vf@OU?q(a{jC2CkA-yCV}f zxm$mz>R`7|GP(9Xc3OgJe-iBcv8fspHDy^ZmT~_vUV5?b%XCyoXxyrF(kMY*d`UUh zJ<(PB)!tnPHqrOpv5qlg3yv_!ZGKkMBFh#SE<+{uQV4>!xXe#7d&lMfDU zocAszyP0NunQ!nE7 z>(5aE4XY~cTdf6;Shios&8{RnIT|3l|J>ON9NQd@oHp7eKwaJnDi5_>RMW#N6dPfr zRiWeo38(~I5=pP^fmRpl)#0AtX#chB!fhCr8?K1zSt@`&;9vY9gHswhsnwqChed~nRfRF>8b(R_zCJKP?nSaq2jQu&AGVx z;i#gpbcV}J&1mXp=_#q{(w$Q@dh@7l5vYO~Szhka<#wBS;Eh~${ul5d>G9&2|3fbZ zH5|>!+{T7TAKR;*A8S}y0Y|!(>MY9Y9nx2sWmV8egBHY3;W=V-j10T(M_9!Viq-@6 zrUI1LmsIJzj8UVngk?**kjXn;l11~!GjA0mwiWaV=WnHxmhMI}qClIFy`;u2Ed&X? zJ6!R*I%&ZGL8S=AeNd-*(mNF6gDDPP#+e7tR&8b|+>U2DPEcDmY;ce03*#@OS!y9q zu^f9(IlgZ2a=aGC!orB-D%d(EdhzlGS4Izp!`i}=WfI()-+(8td{Rm zbVF2{NI~a@-M%o1>jd!wvzVh45{|_{BMiwzmBioPw%NMhAbQ8i3w~6LliO~kK`&Mx zRpN}o%-5T-EPugCYp}*J)bVB(mZR@pezgh$AY}CL-N(%0MX(I`Qu%s?f@sH1dbQ<{ zT2c&hmMoP)_D2CW2I8Q^HX@+HrP=sK0rTK6zE-GH5SNHW?%N7?6;An#Rl>P;pfXW&O7ryF zmJD~-##QhvY=89`+!(iD`lR*eOzS8mu}G`h=w!652(5{jrBgTT=*ja%6Y!1KX&?@+ zlLDb8E%daDGmP;_3`bTd9dcuke_O-LxrG@2*T?I=Ubx5Zj?`FTWN^DRyxXS70HYL< zymtewOYCpfrjY4@F_5IYftcEs6Yy{>Xt_Hrka_dlbJrs8jxEZBT-!7$F6(A_^33=a zkV-{WoOzvxS715(F~Oi_q@{!+w?Hv2o+7ql;kALv4r$?E}$W3vB~LsH zJRhU@>B*BP@?L8n7EhC&KYlE-C4~iu4vPo=z#W6#Pr!;4xq+`-_p7++QF9L { ).map((chip) => (chip.textContent ?? "").replace(/\s+/g, " ").trim()); } - /** The chip renders `#name` with an sr-only "Private" marker. */ + /** The chip renders `#name` followed by a "Private" badge when it is one. */ private static toChannelChip(text: string): SelectedChannelChip { return { isPrivate: /Private/.test(text), diff --git a/ui/app/(prowler)/integrations/slack/slack-integration.harness.ts b/ui/app/(prowler)/integrations/slack/slack-integration.harness.ts index b3b735cad0..3504f72ef5 100644 --- a/ui/app/(prowler)/integrations/slack/slack-integration.harness.ts +++ b/ui/app/(prowler)/integrations/slack/slack-integration.harness.ts @@ -15,6 +15,10 @@ import type { SlackFixture } from "@/__tests__/msw/handlers/slack.fixtures"; import { worker } from "@/__tests__/msw/worker"; import { render } from "@/__tests__/render-browser"; import { setSlackAuthorizedChannels } from "@/actions/integrations/slack"; +import { + CHECK_STATUS, + type CheckStatus, +} from "@/components/integrations/slack/slack-connection-check-status"; import { SLACK_CONNECT_PARAMS } from "@/lib/integrations/slack-connect-status"; import { IntegrationsContent } from "../integrations-content"; @@ -335,6 +339,69 @@ export class SlackIntegrationHarness extends BrowserHarness { ); } + async connectionSuccessToast(): Promise { + return this.waitFor( + () => this.toastText(/Connection test successful/), + 15000, + "the connection success toast", + ); + } + + /** + * The check's standing state, read from the card's own marker. The status is + * the card's alone: the toast reports a check that just ran and then goes, + * where this retires on its own once the channels it covered have moved. + */ + async connectionCheckStatus(): Promise { + const region = await this.waitFor( + () => this.q("[data-connection-check-status]"), + 10000, + "the connection check status", + ); + return region.getAttribute("data-connection-check-status") as CheckStatus; + } + + /** + * What the card says the last check found, or null when it shows no outcome + * at all. The element is always mounted — `sr-only` while empty — so an empty + * one has to read as "no outcome", not as an outcome that says nothing. + */ + connectionCheckOutcome(): string | null { + const outcome = this.q("[data-connection-check-outcome]"); + return (outcome?.textContent ?? "").replace(/\s+/g, " ").trim() || null; + } + + /** The same copy, waited for: the outcome lands a render after the answer. */ + async connectionCheckOutcomeText(): Promise { + return this.waitFor( + () => this.connectionCheckOutcome(), + 15000, + "the connection check outcome", + ); + } + + /** + * Wait until the card has taken its finding back — no outcome, and resting. + * Both, together: a status that says nothing while the line it decorated is + * still on screen would be the half-retired state the derivation exists to + * make impossible. + */ + async waitForRetiredConnectionCheck(): Promise { + await this.waitFor( + () => { + const status = this.q("[data-connection-check-status]")?.getAttribute( + "data-connection-check-status", + ); + return status === CHECK_STATUS.IDLE && + this.connectionCheckOutcome() === null + ? true + : null; + }, + 10000, + "the connection check finding to be retired", + ); + } + /** * The "last checked" line as rendered, or null when the page shows none — * which is what a workspace whose connection was never checked shows. @@ -342,7 +409,7 @@ export class SlackIntegrationHarness extends BrowserHarness { lastCheckedLine(): string | null { const line = Array.from( this.container.querySelectorAll("p"), - ).find((p) => /^Last checked:/.test((p.textContent ?? "").trim())); + ).find((p) => /^Last checked\b/.test((p.textContent ?? "").trim())); return line ? (line.textContent ?? "").trim() : null; } @@ -350,16 +417,24 @@ export class SlackIntegrationHarness extends BrowserHarness { return this.countRequests("POST", "/connection"); } - /** The outcome of a check under way, started by the button or by a save. */ + /** + * The outcome of a check under way, started by the button or by a save, read + * from the card's status. + * + * Deliberately not read from the copy: the toast titles the page has always + * raised are the only text saying "Connection test succeeded/failed", and + * they are portaled outside the card — so a reader going by text would settle + * on the toast and report an outcome the card never showed. The toasts have + * assertions of their own, which is what keeps the two surfaces independent. + */ async connectionOutcome(): Promise { return this.waitFor( () => { - if (this.containsText(/Connection test successful/)) { - return CONNECTION_OUTCOME.SUCCESS; - } - if (this.containsText(/Connection test failed/)) { - return CONNECTION_OUTCOME.FAILURE; - } + const status = this.q("[data-connection-check-status]")?.getAttribute( + "data-connection-check-status", + ); + if (status === CHECK_STATUS.PASSED) return CONNECTION_OUTCOME.SUCCESS; + if (status === CHECK_STATUS.FAILED) return CONNECTION_OUTCOME.FAILURE; return null; }, 15000, @@ -508,8 +583,8 @@ export class SlackIntegrationHarness extends BrowserHarness { /** * Re-read the workspace's channels, the way a user does after inviting - * `@Prowler` to one in Slack. Waits for the read to have settled, not for the - * click alone. + * `@Prowler Cloud` to one in Slack. Waits for the read to have settled, not + * for the click alone. */ async refreshChannels(): Promise { const readsBefore = this.channelListCallCount; @@ -783,11 +858,16 @@ export class SlackIntegrationHarness extends BrowserHarness { "the authorized channel chips", ); + // Order-insensitive: where the chip puts its "Private" marker relative to + // the name is a presentation choice, not something to assert through. return chips.map((chip) => { const text = (chip.textContent ?? "").trim(); return { - name: text.replace(/^Private/, "").replace(/^#/, ""), - isPrivate: /^Private/.test(text), + name: text + .replace(/Private/g, "") + .replace(/^#/, "") + .trim(), + isPrivate: /Private/.test(text), }; }); } @@ -825,14 +905,27 @@ export class SlackIntegrationHarness extends BrowserHarness { return this.containsText(/Could not read the workspace/); } + private channelInviteHintParagraph(): HTMLElement | null { + return ( + Array.from(this.container.querySelectorAll("p")).find( + (element) => /invites? @Prowler Cloud/.test(element.textContent ?? ""), + ) ?? null + ); + } + /** The invite copy that says how to make a private channel appear. */ channelInviteHint(): string | null { - const hint = Array.from( - this.container.querySelectorAll("p"), - ).find((element) => /invites? @Prowler/.test(element.textContent ?? "")); + const hint = this.channelInviteHintParagraph(); return hint ? (hint.textContent ?? "").trim() : null; } + /** Where the invite hint sends a user stuck on a missing private channel. */ + channelInviteHintDocsUrl(): string | null { + const link = + this.channelInviteHintParagraph()?.querySelector("a"); + return link ? link.href : null; + } + // --- Disconnecting ------------------------------------------------------ get disconnectCallCount(): number { diff --git a/ui/app/(prowler)/integrations/slack/slack-page.integration.test.tsx b/ui/app/(prowler)/integrations/slack/slack-page.integration.test.tsx index 05235da60c..96292509e1 100644 --- a/ui/app/(prowler)/integrations/slack/slack-page.integration.test.tsx +++ b/ui/app/(prowler)/integrations/slack/slack-page.integration.test.tsx @@ -205,8 +205,24 @@ describe("a connected workspace", () => { expect(await harness.connectedWorkspaceName()).toBe(WORKSPACE_NAME); expect(await harness.connectionBadge()).toBe("Connected"); + // Read positively as well as negatively (:254): without this, a reworded + // line the harness stops recognising would leave that null-only check + // passing vacuously. + expect(harness.lastCheckedLine()).toMatch(/2026\/08\/10/); expect(await harness.offersConnectionTest()).toBe(true); expect(await harness.testConnection()).toBe(CONNECTION_OUTCOME.SUCCESS); + // And — the card says what the check reached, naming the one channel it + // covered. Asserted off the card's own region, not the page's text: the + // toast below says "Connection test successful" too, so a text match would + // stand with this line never rendered. + expect(await harness.connectionCheckOutcomeText()).toBe( + `#${SLACK_PUBLIC_CHANNEL.name} is reachable.`, + ); + // And — the toast, which is the other half and goes on its own. Read + // separately so neither surface can vouch for the other. + expect(await harness.connectionSuccessToast()).toMatch( + /Connection test successful/, + ); // One workspace per tenant (design D10): no second install on offer, and no // consent URL minted for a page that would never use it. expect(harness.offersInstall()).toBe(false); @@ -356,8 +372,8 @@ describe("authorizing destination channels", () => { }, 60000); it("offers a private channel the app was invited to, marked as private, and authorizes it", async () => { - // Given — `@Prowler` was invited to one private channel; `groups:read` is - // membership-gated (D2). + // Given — `@Prowler Cloud` was invited to one private channel; + // `groups:read` is membership-gated (D2). const harness = new SlackIntegrationHarness(connectedSlackFixture()); await harness.mount(); @@ -381,7 +397,7 @@ describe("authorizing destination channels", () => { ]); }, 60000); - it("offers a private channel once @Prowler is invited to it and the list is refreshed", async () => { + it("offers a private channel once @Prowler Cloud is invited to it and the list is refreshed", async () => { // Given — a workspace whose only channels are public: `groups:read` is // membership-gated (design D2). const harness = new SlackIntegrationHarness( @@ -397,8 +413,8 @@ describe("authorizing destination channels", () => { SLACK_PRIVATE_CHANNEL.name, ); - // When — `@Prowler` is invited to a private channel, and the user refreshes - // instead of reconnecting the workspace. + // When — `@Prowler Cloud` is invited to a private channel, and the user + // refreshes instead of reconnecting the workspace. harness.fixture.channels.push({ ...SLACK_PRIVATE_CHANNEL }); await harness.refreshChannels(); @@ -423,7 +439,7 @@ describe("authorizing destination channels", () => { // Then — the user is told what to do, not merely that the list is empty. const message = await harness.channelPickerMessage(); expect(message).toMatch(/No channels available yet/); - expect(message).toMatch(/invite @Prowler/); + expect(message).toMatch(/invite @Prowler Cloud/); expect(await harness.authorizedChannels()).toEqual([]); expect(await harness.offersConnectionTest()).toBe(false); }, 30000); @@ -443,6 +459,12 @@ describe("authorizing destination channels", () => { // Then expect(await harness.connectionOutcome()).toBe(CONNECTION_OUTCOME.SUCCESS); expect(harness.connectionCheckCallCount).toBe(1); + // And — the card names the channel the chained check covered, which the + // save hands it directly: the set the check ran against is not on record + // as state yet when the summary is built. + expect(await harness.connectionCheckOutcomeText()).toBe( + `#${SLACK_PUBLIC_CHANNEL.name} is reachable.`, + ); // And — everything waiting on a destination moves with the save, in the // same paint: no reload to find the check on offer for later. expect(await harness.offersConnectionTest()).toBe(true); @@ -474,6 +496,11 @@ describe("authorizing destination channels", () => { // Then — only the check failed, so the destinations stay on record, and // the failure names the one channel Slack refused. expect(await harness.connectionOutcome()).toBe(CONNECTION_OUTCOME.FAILURE); + // The card and the toast each name it, and each is read where it lives: + // the toast goes, and what the card keeps is what the user comes back to. + expect(await harness.connectionCheckOutcomeText()).toMatch( + new RegExp(`^Slack refused #${SLACK_PRIVATE_CHANNEL.name}\\b`), + ); expect(await harness.connectionFailureToast()).toMatch( new RegExp(`Slack refused #${SLACK_PRIVATE_CHANNEL.name}`), ); @@ -516,6 +543,41 @@ describe("authorizing destination channels", () => { expect(harness.offersChannelsSave()).toBe(false); }, 60000); + it("takes back a passing result once the set it vouched for is no longer the set on record", async () => { + // Given — a check that passed against the one channel then authorized, said + // in the card in those terms. + const harness = new SlackIntegrationHarness(configuredSlackFixture()); + await harness.mount(); + expect(await harness.testConnection()).toBe(CONNECTION_OUTCOME.SUCCESS); + expect(await harness.connectionCheckOutcomeText()).toBe( + `#${SLACK_PUBLIC_CHANNEL.name} is reachable.`, + ); + + // When — a channel nothing has checked joins the record, from elsewhere, so + // no new check runs to overwrite the standing one. + await harness.channelsRecordedElsewhere([ + SLACK_PUBLIC_CHANNEL.name, + SLACK_SECOND_PUBLIC_CHANNEL.name, + ]); + await harness.refreshPageData(); + + // Then — the result is withdrawn rather than left standing: a line saying + // the channels are reachable, over a set one of them was never tried + // against, would be a claim the check never made. + await harness.waitForRetiredConnectionCheck(); + // And — the badge steps back with it, because the record does too: the API + // clears its own verdict on a changed set for the same reason the card + // clears the finding, so the two never disagree about what was checked. + expect(await harness.connectionBadge()).toBe("Not checked yet"); + // And — only the finding is withdrawn, not the setup: the wider set is on + // record, with the check still there to be run over it. + expect(await harness.authorizedChannels()).toEqual([ + SLACK_PUBLIC_CHANNEL.name, + SLACK_SECOND_PUBLIC_CHANNEL.name, + ]); + expect(await harness.offersConnectionTest()).toBe(true); + }, 60000); + it("says which permission is missing when Slack refuses the channel listing, leaving the authorized set alone", async () => { // Given — an authorized set, and an install missing a scope the listing // needs. The API names it in `code` (contract, Errors), not in `detail`. @@ -536,7 +598,7 @@ describe("authorizing destination channels", () => { // Slack's reason is a protocol token: it travels in `code` and is never // shown. expect(message).not.toMatch(SLACK_MISSING_SCOPE_CODE); - expect(harness.channelInviteHint()).toMatch(/invites @Prowler/); + expect(harness.channelInviteHint()).toMatch(/invites @Prowler Cloud/); // And — a listing Prowler could not read says nothing about the channels // already authorized. @@ -546,6 +608,20 @@ describe("authorizing destination channels", () => { expect(await harness.offersConnectionTest()).toBe(true); }, 30000); + it("sends a user stuck on a missing private channel to the docs section about it", async () => { + // Given — a connected workspace, so the picker's invite copy is on screen. + const harness = new SlackIntegrationHarness(connectedSlackFixture()); + + // When + await harness.mount(); + + // Then — the whole anchored URL: the anchor is the point of the link, and + // it is derived from a docs heading that a rewording would silently move. + expect(harness.channelInviteHintDocsUrl()).toBe( + "https://docs.prowler.com/user-guide/tutorials/prowler-app-slack-integration#why-a-private-channel-is-missing-from-the-channel-list", + ); + }, 30000); + it("names the wait Slack asked for when it rate limits the channel listing", async () => { // Given — `conversations.list` is Slack tier 2 and paginated (contract, // Errors); the `429` carries the wait in `Retry-After`. @@ -632,7 +708,7 @@ describe("authorizing destination channels", () => { ]); }, 30000); - it("says to invite @Prowler when Slack refuses a channel because the app is not in it", async () => { + it("says to invite @Prowler Cloud when Slack refuses a channel because the app is not in it", async () => { // Given — a private channel the app was removed from. The API validates the // set against Slack on the way in and refuses with `not_in_channel`. const harness = new SlackIntegrationHarness( @@ -649,7 +725,7 @@ describe("authorizing destination channels", () => { // Then — the one fix the user can carry out themselves, in Slack. expect(refusal).toMatch(/Prowler is not in that channel/); - expect(refusal).toMatch(/Invite @Prowler to it in Slack/); + expect(refusal).toMatch(/Invite @Prowler Cloud to it in Slack/); expect(refusal).not.toMatch(SLACK_NOT_IN_CHANNEL_CODE); // And — nothing was recorded, so there is still nothing to check against. @@ -657,7 +733,7 @@ describe("authorizing destination channels", () => { expect(await harness.offersConnectionTest()).toBe(false); }, 60000); - it("says the channel is gone, not that @Prowler needs inviting, when Slack no longer has it", async () => { + it("says the channel is gone, not that @Prowler Cloud needs inviting, when Slack no longer has it", async () => { // Given — a channel archived since the listing was read. The API's `detail` // is word-for-word the one for `not_in_channel`, so only `code` tells them // apart. @@ -677,7 +753,7 @@ describe("authorizing destination channels", () => { // channel that no longer exists. expect(refusal).toMatch(/no longer exists in the workspace/); expect(refusal).toMatch(/Choose another one/); - expect(refusal).not.toMatch(/Invite @Prowler/); + expect(refusal).not.toMatch(/Invite @Prowler Cloud/); expect(refusal).not.toMatch(SLACK_UNKNOWN_CHANNEL_DETAIL); expect(await harness.authorizedChannels()).toEqual([]); }, 60000); @@ -689,7 +765,7 @@ describe("authorizing destination channels", () => { // Then — checking again posts nothing: the confirmation is one-time // (design D7), not a fresh message every run. - expect(harness.connectionCheckHint()).toMatch(/nothing is posted/); + expect(harness.connectionCheckHint()).toMatch(/Nothing is posted/); expect(harness.connectionCheckHint()).not.toMatch(/test message/i); // When — a second channel is authorized. @@ -711,7 +787,7 @@ describe("authorizing destination channels", () => { expect(await harness.connectionOutcome()).toBe(CONNECTION_OUTCOME.SUCCESS); await harness.refreshPageData(); expect( - await harness.connectionCheckHintMatching(/nothing is posted/), + await harness.connectionCheckHintMatching(/Nothing is posted/), ).toMatch(/every authorized channel/); }, 60000); @@ -831,7 +907,7 @@ describe("authorizing destination channels", () => { // Given — a finished setup whose channel an earlier check confirmed. const harness = new SlackIntegrationHarness(configuredSlackFixture()); await harness.mount(); - expect(harness.connectionCheckHint()).toMatch(/nothing is posted/); + expect(harness.connectionCheckHint()).toMatch(/Nothing is posted/); // When — the same workspace is approved again. The exchange is the // callback route's doing (covered in `callback/route.test.ts`); here it diff --git a/ui/changelog.d/slack-connection-check-result.added.md b/ui/changelog.d/slack-connection-check-result.added.md new file mode 100644 index 0000000000..f671f90151 --- /dev/null +++ b/ui/changelog.d/slack-connection-check-result.added.md @@ -0,0 +1 @@ +Slack integration: the connection check leaves its result on the card instead of only in a toast, naming the channel Slack refused or the channels it reached (Prowler Cloud only) diff --git a/ui/changelog.d/slack-private-channel-marker.changed.md b/ui/changelog.d/slack-private-channel-marker.changed.md new file mode 100644 index 0000000000..0c25848b5a --- /dev/null +++ b/ui/changelog.d/slack-private-channel-marker.changed.md @@ -0,0 +1 @@ +Slack integration: a selected private channel carries the same visible `Private` badge as the channel list, replacing the lock icon on the chip (Prowler Cloud only) diff --git a/ui/changelog.d/slack-ui-feedback.changed.md b/ui/changelog.d/slack-ui-feedback.changed.md new file mode 100644 index 0000000000..33708de1b0 --- /dev/null +++ b/ui/changelog.d/slack-ui-feedback.changed.md @@ -0,0 +1 @@ +Slack integration: the bot is referred to as `@Prowler Cloud`, identifiers are set as inline code, and the private-channel hint links to its docs (Prowler Cloud only) diff --git a/ui/components/integrations/shared/integration-card-header.tsx b/ui/components/integrations/shared/integration-card-header.tsx index e78f12ed0d..b7f247a41b 100644 --- a/ui/components/integrations/shared/integration-card-header.tsx +++ b/ui/components/integrations/shared/integration-card-header.tsx @@ -10,17 +10,18 @@ import { cn } from "@/lib/utils"; const CONNECTION_BADGE = { connected: { label: "Connected", - className: - "bg-bg-pass-secondary text-text-success-primary border-transparent", + variant: "success", + dotClassName: "bg-bg-pass", }, disconnected: { label: "Disconnected", - className: - "bg-bg-fail-secondary text-text-error-primary border-transparent", + variant: "error", + dotClassName: "bg-bg-fail", }, unchecked: { label: "Not checked yet", - className: "border-border-tag bg-bg-tag text-text-neutral-secondary", + variant: "tag", + dotClassName: "bg-bg-data-muted", }, } as const; @@ -45,30 +46,57 @@ interface IntegrationCardHeaderProps { icon: ReactNode; title: string; subtitle?: string; + /** + * A quiet third line under the subtitle, for a fact about the integration + * rather than a claim about it — when its connection was last checked, say. + */ + meta?: ReactNode; chips?: IntegrationCardChip[]; connectionStatus?: IntegrationConnectionStatus; navigationUrl?: string; + /** The integration's own controls, pinned to the end of the row. */ + actions?: ReactNode; } export const IntegrationCardHeader = ({ icon, title, subtitle, + meta, chips = [], connectionStatus, navigationUrl, + actions, }: IntegrationCardHeaderProps) => { const badgeState = connectionStatus ? connectionBadgeState(connectionStatus.connected) : null; const badge = badgeState ? CONNECTION_BADGE[badgeState] : null; + // The end of the row belongs to the controls wherever there are any, so the + // status travels with the name it qualifies instead of across the card. + const statusBesideTitle = Boolean(actions); + + const statusBadge = + badge && badgeState ? ( + + + ) : null; + + const hasAside = + chips.length > 0 || Boolean(actions) || (statusBadge && !statusBesideTitle); + return (

{icon} -
-
+
+

{title}

{navigationUrl && (
)} + {statusBesideTitle && statusBadge}
{subtitle && ( -

- {subtitle} -

+

{subtitle}

)} + {meta}
- {(chips.length > 0 || badge) && ( + {hasAside && (
{chips.map((chip, index) => ( {chip.label} ))} - {badge && badgeState && ( - - {connectionStatus?.label || badge.label} - - )} + {!statusBesideTitle && statusBadge} + {actions}
)}
diff --git a/ui/components/integrations/slack/slack-channel-multi-select.tsx b/ui/components/integrations/slack/slack-channel-multi-select.tsx index 08d07f67b6..02d4d4f88e 100644 --- a/ui/components/integrations/slack/slack-channel-multi-select.tsx +++ b/ui/components/integrations/slack/slack-channel-multi-select.tsx @@ -1,7 +1,8 @@ "use client"; -import { Lock, RefreshCw } from "lucide-react"; +import { RefreshCw } from "lucide-react"; +import { SlackInlineCode } from "@/components/integrations/slack/slack-inline-code"; import { Alert, AlertDescription, @@ -10,6 +11,7 @@ import { Button, Label, } from "@/components/shadcn"; +import { CustomLink } from "@/components/shadcn/custom/custom-link"; import { MultiSelect, MultiSelectContent, @@ -17,10 +19,23 @@ import { MultiSelectTrigger, MultiSelectValue, } from "@/components/shadcn/select/multiselect"; +import { DOCS_URLS } from "@/lib/external-urls"; import type { SlackChannelOption } from "@/types/integrations"; -const INVITE_HINT = - "A private channel only appears here after someone invites @Prowler to it in Slack. Invite it, then refresh."; +const INVITE_HINT = ( + <> + A private channel only appears here after someone invites{" "} + @Prowler Cloud to it in Slack. Invite it, + then refresh.{" "} + + Learn more + + +); interface SlackChannelMultiSelectProps { options: SlackChannelOption[]; @@ -38,15 +53,15 @@ interface SlackChannelMultiSelectProps { describedBy?: string; } +/** Marked exactly as the listing marks it, so the chip is the row it came from. */ const chipLabel = (option: SlackChannelOption) => ( - {option.is_private && ( - <> - ); @@ -104,8 +119,10 @@ export const SlackChannelMultiSelect = ({ No channels available yet Prowler cannot see a single channel in this workspace. Create a - public channel, or invite @Prowler to a private one in Slack with - /invite @Prowler, then + public channel, or invite{" "} + @Prowler Cloud to a private one + in Slack with{" "} + /invite @Prowler Cloud, then refresh. diff --git a/ui/components/integrations/slack/slack-connection-check-status.tsx b/ui/components/integrations/slack/slack-connection-check-status.tsx new file mode 100644 index 0000000000..ea925db602 --- /dev/null +++ b/ui/components/integrations/slack/slack-connection-check-status.tsx @@ -0,0 +1,124 @@ +import { Check, CircleAlert, Loader2, type LucideIcon } from "lucide-react"; +import type { ReactNode } from "react"; + +import { cn } from "@/lib/utils"; + +// Read by the page harness off `data-connection-check-status`. +export const CHECK_STATUS = { + /** No check has run against the channels currently on record. */ + IDLE: "idle", + RUNNING: "running", + PASSED: "passed", + FAILED: "failed", +} as const; + +export type CheckStatus = (typeof CHECK_STATUS)[keyof typeof CHECK_STATUS]; + +interface CheckStatusStyle { + /** `null` for the resting state, which shows no outcome to decorate. */ + icon: LucideIcon | null; + className: string; +} + +const CHECK_STATUS_STYLES = { + [CHECK_STATUS.IDLE]: { + icon: null, + className: "", + }, + [CHECK_STATUS.RUNNING]: { + icon: Loader2, + className: + "border-border-neutral-secondary bg-bg-neutral-tertiary text-text-neutral-secondary", + }, + // The dark pass tokens are sized for a whole card, and at this width they + // read as an alert rather than a note, so they are taken down a shade there. + [CHECK_STATUS.PASSED]: { + icon: Check, + className: + "border-bg-pass bg-bg-pass-secondary text-text-success-primary dark:border-bg-pass/40 dark:bg-bg-pass-secondary/40", + }, + [CHECK_STATUS.FAILED]: { + icon: CircleAlert, + className: + "border-border-error bg-bg-fail-secondary text-text-error-primary dark:border-border-error/50", + }, +} as const satisfies Record; + +interface SlackConnectionCheckStatusProps { + status: CheckStatus; + /** What the last check found. Absent while no check covers the record. */ + outcome?: ReactNode; + /** + * Id the control points at with `aria-describedby`. The caption alone carries + * it: an outcome read out as the control's description would say what the + * last check did, where the description has to say what pressing it does. + */ + captionId: string; + /** What the check does, or why it cannot run. */ + children: ReactNode; +} + +/** + * The connection check's standing state: what a check last found, over the + * caption explaining what running one does. + * + * The two are kept in separate registers — the outcome boxed, the caption plain + * underneath — because they are answers to different questions and can honestly + * disagree. A refused channel is still a channel the next check will try, so + * reading the caption as a continuation of the outcome ("Slack refused #ops" … + * "posts the confirmation to #ops") would turn a true pair of statements into a + * contradiction. + */ +export const SlackConnectionCheckStatus = ({ + status, + outcome, + captionId, + children, +}: SlackConnectionCheckStatusProps) => { + const { icon: Icon, className } = CHECK_STATUS_STYLES[status]; + + return ( +
+
+ {Icon && outcome && ( +
+

+ {children} +

+
+ ); +}; diff --git a/ui/components/integrations/slack/slack-inline-code.tsx b/ui/components/integrations/slack/slack-inline-code.tsx new file mode 100644 index 0000000000..a197148d47 --- /dev/null +++ b/ui/components/integrations/slack/slack-inline-code.tsx @@ -0,0 +1,15 @@ +import type { ReactNode } from "react"; + +interface SlackInlineCodeProps { + children: ReactNode; +} + +/** + * A Slack identifier — a channel name, the bot mention, a slash command — set + * apart from the prose around it. + */ +export const SlackInlineCode = ({ children }: SlackInlineCodeProps) => ( + + {children} + +); diff --git a/ui/components/integrations/slack/slack-integration-card.tsx b/ui/components/integrations/slack/slack-integration-card.tsx index a4e8397afb..619e9242c9 100644 --- a/ui/components/integrations/slack/slack-integration-card.tsx +++ b/ui/components/integrations/slack/slack-integration-card.tsx @@ -4,9 +4,7 @@ import Link from "next/link"; import { SlackIcon } from "@/components/icons/services/IconServices"; import { Button, Card, CardContent, CardHeader } from "@/components/shadcn"; import { CustomLink } from "@/components/shadcn/custom/custom-link"; - -const SLACK_DOCS_URL = - "https://docs.prowler.com/user-guide/tutorials/prowler-app-slack-integration"; +import { DOCS_URLS } from "@/lib/external-urls"; export const SlackIntegrationCard = () => { return ( @@ -24,7 +22,7 @@ export const SlackIntegrationCard = () => { Send Prowler messages to your Slack workspace.

diff --git a/ui/components/integrations/slack/slack-integration-manager.tsx b/ui/components/integrations/slack/slack-integration-manager.tsx index 66c6e9c9f7..fdbfbcc502 100644 --- a/ui/components/integrations/slack/slack-integration-manager.tsx +++ b/ui/components/integrations/slack/slack-integration-manager.tsx @@ -2,7 +2,7 @@ import { format, isValid, parseISO } from "date-fns"; import { TestTube, Unplug } from "lucide-react"; -import { useEffect, useState } from "react"; +import { type ReactNode, useEffect, useState } from "react"; import { testIntegrationConnection } from "@/actions/integrations/integrations"; import { @@ -14,6 +14,12 @@ import { import { SlackIcon } from "@/components/icons/services/IconServices"; import { IntegrationCardHeader } from "@/components/integrations/shared"; import { SlackChannelMultiSelect } from "@/components/integrations/slack/slack-channel-multi-select"; +import { + CHECK_STATUS, + type CheckStatus, + SlackConnectionCheckStatus, +} from "@/components/integrations/slack/slack-connection-check-status"; +import { SlackInlineCode } from "@/components/integrations/slack/slack-inline-code"; import { Alert, AlertDescription, @@ -76,6 +82,20 @@ interface UnconfirmedRevocation { workspace: string | null; } +/** + * What the last check found, together with what it was measured against. Both + * ride with the finding so it can never outlive them: a green line vouching for + * a channel nothing ever reached is worse than no line at all, and so is one + * standing over a notice saying the credential is dead. + */ +interface ConnectionCheckOutcome { + reachable: boolean; + summary: string; + channelIds: string[]; + /** The credential verdict the check was run under. */ + credentialFailure: SlackTokenErrorCode | null; +} + /** Order-insensitive: the mirror must not re-seed on a mere reordering. */ const sameChannelIds = (a: string[], b: string[]) => a.length === b.length && new Set([...a, ...b]).size === a.length; @@ -129,10 +149,39 @@ const recordedFromSelection = ( ]; }); +const CHANNEL_LIST_FORMAT = new Intl.ListFormat("en", { + style: "long", + type: "conjunction", +}); + +const channelTokens = (names: string[]): string[] => + names.map((name) => `#${name}`); + +/** For the copy that travels as plain text: toasts, the deauthorize warning. */ const channelList = (names: string[]): string => - new Intl.ListFormat("en", { style: "long", type: "conjunction" }).format( - names.map((name) => `#${name}`), - ); + CHANNEL_LIST_FORMAT.format(channelTokens(names)); + +interface StyledChannelListProps { + names: string[]; +} + +/** + * The same list as `channelList()`, each channel set apart. `formatToParts` + * emits exactly the literals `format` joins, so the rendered text is unchanged + * (design D3) — the copy is read as text content, here and by the tests. + */ +const StyledChannelList = ({ names }: StyledChannelListProps) => ( + <> + {CHANNEL_LIST_FORMAT.formatToParts(channelTokens(names)).map( + (part, index) => + part.type === "element" ? ( + {part.value} + ) : ( + part.value + ), + )} + +); /** * Slack's own reason, when the string is one: the connection check reports a @@ -160,6 +209,10 @@ export const SlackIntegrationManager = ({ loadError, }: SlackIntegrationManagerProps) => { const [isTesting, setIsTesting] = useState(false); + // A check's finding outlives its toast: the card keeps saying where the + // workspace stands until a change to the channels makes the finding moot. + const [checkOutcome, setCheckOutcome] = + useState(null); const [isDisconnectOpen, setIsDisconnectOpen] = useState(false); const [isDisconnecting, setIsDisconnecting] = useState(false); // The row is gone the moment the API says so; the server component's @@ -317,15 +370,55 @@ export const SlackIntegrationManager = ({ (channel) => !selectedChannelIds.includes(channel.id), ); - const checkHint = (): string => { + const authorizedChannelIds = authorizedChannels.map((channel) => channel.id); + + /** + * Derived, not stored, so a finding retires on its own the moment anything it + * was measured against moves: a channel authorized or dropped leaves a set no + * check has covered, and a credential verdict that has since changed leaves a + * finding taken under conditions that no longer hold. + */ + const coveredOutcome = + checkOutcome && + sameChannelIds(checkOutcome.channelIds, authorizedChannelIds) && + checkOutcome.credentialFailure === credentialFailure + ? checkOutcome + : null; + + const checkStatus = (): CheckStatus => { + if (isTesting) return CHECK_STATUS.RUNNING; + if (!coveredOutcome) return CHECK_STATUS.IDLE; + return coveredOutcome.reachable ? CHECK_STATUS.PASSED : CHECK_STATUS.FAILED; + }; + + // Deliberately not a second telling of the caption below it: the button + // already reads "Testing...", so this only has to say a check is under way. + const checkSummary = isTesting + ? "Checking the connection..." + : coveredOutcome?.summary; + + /** What a passing check proves, said in terms of what was actually reached. */ + const reachableSummary = (channels: SlackAuthorizedChannel[]): string => + channels.length === 1 + ? `#${channels[0].name} is reachable.` + : `All ${channels.length} channels are reachable.`; + + const checkHint = (): ReactNode => { if (authorizedChannels.length === 0) { return "Authorize at least one destination channel below to enable this check."; } - return unconfirmedChannels.length > 0 - ? `Checks every authorized channel and posts “${CONFIRMATION_MESSAGE}” once to ${channelList( - unconfirmedChannels.map((channel) => channel.name), - )}.` - : "Checks every authorized channel. Each was confirmed once already, so nothing is posted."; + return unconfirmedChannels.length > 0 ? ( + <> + Checks every authorized channel and posts “{CONFIRMATION_MESSAGE}” once + to{" "} + channel.name)} + /> + . + + ) : ( + "Checks every authorized channel. Nothing is posted." + ); }; const handleSaveChannels = async () => { @@ -395,12 +488,24 @@ export const SlackIntegrationManager = ({ // Passed in by a chained check: it runs before the save's state lands. channels: SlackAuthorizedChannel[] = authorizedChannels, ) => { + const checkedChannelIds = channels.map((channel) => channel.id); + setIsTesting(true); try { const result = await testIntegrationConnection(id); if (result.success) { provedCredentialAlive(); + setCheckOutcome({ + reachable: true, + // Prowler's own count, not the API's prose: the line has to keep + // meaning the same thing every time it is read. + summary: reachableSummary(channels), + channelIds: checkedChannelIds, + // An answer at all clears the verdict, so a pass is always taken + // under a live credential. + credentialFailure: null, + }); toast({ title: "Connection test successful!", description: @@ -411,8 +516,13 @@ export const SlackIntegrationManager = ({ // A dead credential named here is not a failure checking again can // fix, so the reason is recorded and not only reported. const reason = result.error?.trim() || null; + const reasonCode = asReasonCode(reason); - recordRefusal(asReasonCode(reason)); + recordRefusal(reasonCode); + + // The verdict this check leaves behind: its own reason when it named + // one, else the last answer's, which nothing here contradicted. + const codeAfterCheck = reasonCode ?? lastRefusalCode; const explanation = reason ? slackErrorMessage({ code: reason, detail: reason }) @@ -424,15 +534,32 @@ export const SlackIntegrationManager = ({ ? channels.find((channel) => channel.id === result.failedChannelId) : undefined; + const refusal = refusedChannel + ? `Slack refused #${refusedChannel.name}: ${explanation}` + : explanation; + + setCheckOutcome({ + reachable: false, + summary: refusal, + channelIds: checkedChannelIds, + credentialFailure: isSlackTokenErrorCode(codeAfterCheck) + ? codeAfterCheck + : null, + }); toast({ variant: "destructive", title: "Connection test failed", - description: refusedChannel - ? `Slack refused #${refusedChannel.name}: ${explanation}` - : explanation, + description: refusal, }); } } catch (_error) { + setCheckOutcome({ + reachable: false, + summary: "Prowler could not reach Slack to run the check.", + channelIds: checkedChannelIds, + // Never an answer from Slack, so the standing verdict is untouched. + credentialFailure, + }); toast({ variant: "destructive", title: "Error", @@ -607,11 +734,18 @@ export const SlackIntegrationManager = ({ ) : integration && !disconnected ? ( - + } title={`Connected to ${workspaceName ?? "your Slack workspace"}`} subtitle="Prowler posts to this workspace only." + meta={ + lastCheckedOn && ( +

+ Last checked {lastCheckedOn} +

+ ) + } connectionStatus={{ // A dead token outranks the state the page was loaded with. connected: @@ -619,21 +753,8 @@ export const SlackIntegrationManager = ({ ? integration.attributes.connected : false, }} - /> -
- - -
-
- {lastCheckedOn && ( -

- Last checked:{" "} - {lastCheckedOn} -

- )} -
-
-
+ actions={ + <> {/* The check reaches the authorized channels: the API answers 400 while the set is empty. */} -
-

- {checkHint()} -

-
-
+ + } + /> -
+ {/* Below the row, not beside the buttons: the width is what lets + the check say what it did without wrapping into a column. */} + + {checkHint()} + + + + +
- {authorizedChannels.length > 0 - ? `Prowler posts to ${channelList( - authorizedChannels.map((channel) => channel.name), - )}.` - : "No destination channels authorized yet."} + {authorizedChannels.length > 0 ? ( + <> + Prowler posts to{" "} + channel.name, + )} + /> + . + + ) : ( + "No destination channels authorized yet." + )}

diff --git a/ui/components/scans/scans-filter-bar.tsx b/ui/components/scans/scans-filter-bar.tsx index de4539651f..f46a29c07a 100644 --- a/ui/components/scans/scans-filter-bar.tsx +++ b/ui/components/scans/scans-filter-bar.tsx @@ -31,7 +31,7 @@ interface ScansFilterBarProps { onScanStatusChange: (value: string) => void; } -const filterItemClass = "w-full md:w-[calc(50%-0.375rem)] xl:w-60"; +const filterItemClass = "w-full sm:max-w-[240px] sm:min-w-[180px] sm:flex-1"; export function ScansFilterBar({ providers, @@ -67,33 +67,37 @@ export function ScansFilterBar({
{showScheduleTypeFilter && ( - +
+ +
)} {showStatusFilter && ( - +
+ +
)} ); diff --git a/ui/components/scans/scans-page-shell.test.tsx b/ui/components/scans/scans-page-shell.test.tsx index 8d67c0d9da..6809cf087b 100644 --- a/ui/components/scans/scans-page-shell.test.tsx +++ b/ui/components/scans/scans-page-shell.test.tsx @@ -336,26 +336,35 @@ describe("ScansPageShell", () => { expect(screen.queryByRole("alert")).not.toBeInTheDocument(); }); - it("keeps launch scan with filters and mutelist with tabs", () => { - vi.stubEnv("UI_CLOUD_ENABLED", "false"); + it("keeps launch scan, import findings, and mutelist with tabs", () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "true"); + // When render( - +
Scans table
, ); - expect( - screen.getByRole("group", { name: /scan filters and actions/i }), - ).toContainElement(screen.getByRole("button", { name: /launch scan/i })); - expect( - screen.getByRole("group", { name: /scan filters and actions/i }), - ).not.toContainElement( - screen.getByRole("link", { name: /configure mutelist/i }), + // Then + const tabs = screen.getByRole("group", { name: /scan tabs/i }); + expect(tabs).toContainElement( + screen.getByRole("button", { name: /launch scan/i }), ); - expect(screen.getByRole("group", { name: /scan tabs/i })).toContainElement( + expect(tabs).toContainElement( + screen.getByRole("button", { name: /import findings/i }), + ); + expect(tabs).toContainElement( screen.getByRole("link", { name: /configure mutelist/i }), ); + expect( + screen.getByRole("group", { name: /scan filters/i }), + ).toContainElement(screen.getByText("Shared scan filters")); }); it("shows the active scans count in the in progress tab", () => { diff --git a/ui/components/scans/scans-page-shell.tsx b/ui/components/scans/scans-page-shell.tsx index 1575c026fc..fc597c95bf 100644 --- a/ui/components/scans/scans-page-shell.tsx +++ b/ui/components/scans/scans-page-shell.tsx @@ -135,8 +135,8 @@ export function ScansPageShell({ )}
- - - {isCloudEnvironment && hasManageIngestionsPermission && ( - - )}
{isCloudEnvironment && } @@ -174,10 +160,10 @@ export function ScansPageShell({
{Object.values(SCAN_JOBS_TAB).map((tab) => ( @@ -186,7 +172,19 @@ export function ScansPageShell({ ))} -
+
+ + {isCloudEnvironment && hasManageIngestionsPermission && ( + + )}
diff --git a/ui/tests/scans/evidence/scans-controls-desktop.png b/ui/tests/scans/evidence/scans-controls-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..d7c7733db37014a5ff2cc7d71882454ccad40e04 GIT binary patch literal 28212 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 literal 0 HcmV?d00001 diff --git a/ui/tests/scans/evidence/scans-controls-mobile.png b/ui/tests/scans/evidence/scans-controls-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..a5308650527cd2ed91fa4733c0bb2efe26306afd GIT binary patch literal 24134 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

C}YU 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 V5i!ah4S~@R7!3hzAz=UiCIF!hxzzvw literal 0 HcmV?d00001 diff --git a/ui/tests/scans/scans-page.ts b/ui/tests/scans/scans-page.ts index 667aaaed85..e75c2d3508 100644 --- a/ui/tests/scans/scans-page.ts +++ b/ui/tests/scans/scans-page.ts @@ -27,10 +27,10 @@ export class ScansPage extends BasePage { // The sidebar exposes its own icon-button labeled "Launch Scan" // (aria-label, wrapped in a Tooltip), so scoping by accessible name // alone hits a strict-mode duplicate. Scope to the page-shell's - // filters-and-actions group, which only contains the visible-text + // tabs-and-actions group, which only contains the visible-text // Launch Scan button. this.launchScanButton = page - .getByRole("group", { name: /scan filters and actions/i }) + .getByRole("group", { name: /scan tabs/i }) .getByRole("button", { name: /^Launch Scan$/i }); this.launchScanDialog = page.getByRole("dialog"); // The modal renders the providers picker as the shared MultiSelect-based diff --git a/ui/tests/scans/scans.md b/ui/tests/scans/scans.md index 5baef3a42d..c2dae769ce 100644 --- a/ui/tests/scans/scans.md +++ b/ui/tests/scans/scans.md @@ -27,7 +27,7 @@ ### Flow Steps 1. Navigate to Scans page -2. Click "Launch Scan" to open the launch scan modal +2. Click "Launch Scan" beside the scan tabs to open the launch scan modal 3. Open the Cloud Account selector and choose the entry whose text contains E2E_AWS_PROVIDER_ACCOUNT_ID 4. Optionally fill Scan Note 5. Click "Launch Scan" in the modal @@ -46,6 +46,7 @@ - Scans page loads correctly - Launch Scan modal opens correctly +- The page-level "Launch Scan" button is located in the "Scan tabs" group, distinct from the sidebar action - Cloud Account select is available and lists the configured provider UID - "Launch Scan" button is rendered and enabled when form is valid - Success toast message: "The scan was launched successfully." From 865eebe7fbd0de32d91856b897588e0c74439ff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Thu, 10 Sep 2026 07:21:27 +0100 Subject: [PATCH 49/77] fix(aws): configurable boto3 timeouts, 10s connect default (#12774) --- .../basic-usage/prowler-cli.mdx | 14 +++ .../providers/aws/boto3-configuration.mdx | 29 +++++- ...s-boto3-connect-timeout-default.changed.md | 1 + .../changelog.d/aws-boto3-timeouts.added.md | 1 + .../aws-retries-max-attempts-zero.fixed.md | 1 + prowler/providers/aws/aws_provider.py | 39 +++++--- prowler/providers/aws/config.py | 27 +++++- .../providers/aws/exceptions/exceptions.py | 13 +++ .../providers/aws/lib/arguments/arguments.py | 23 ++++- .../aws/lib/session/aws_set_up_session.py | 8 +- prowler/providers/common/provider.py | 2 + tests/lib/cli/parser_test.py | 29 ++++++ tests/providers/aws/aws_provider_test.py | 88 +++++++++++++++++++ 13 files changed, 258 insertions(+), 17 deletions(-) create mode 100644 prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md create mode 100644 prowler/changelog.d/aws-boto3-timeouts.added.md create mode 100644 prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md diff --git a/docs/getting-started/basic-usage/prowler-cli.mdx b/docs/getting-started/basic-usage/prowler-cli.mdx index ebf3c6515e..d64bef0b77 100644 --- a/docs/getting-started/basic-usage/prowler-cli.mdx +++ b/docs/getting-started/basic-usage/prowler-cli.mdx @@ -2,6 +2,8 @@ title: 'Basic Usage' --- +import { VersionBadge } from "/snippets/version-badge.mdx" + ## Running Prowler Running Prowler requires specifying the provider (e.g. `aws`, `gcp`, `azure`, `kubernetes`, `m365`, `github`, `iac` or `mongodbatlas`): @@ -91,6 +93,18 @@ By default, `prowler` will scan all AWS regions. See more details about AWS Authentication in the [Authentication Section](/user-guide/providers/aws/authentication) section. +- **AWS Retrier and Timeout Configuration** + + + + Tune the Boto3 standard retrier and the endpoint timeouts when AWS throttles the scan or when some endpoints are unreachable from the network Prowler runs in: + + ```console + prowler aws --aws-retries-max-attempts 5 --aws-connect-timeout 5 --aws-read-timeout 30 + ``` + + See the [Boto3 configuration](/user-guide/providers/aws/boto3-configuration) page for defaults and environment variables. + ## Azure Azure requires specifying the auth method: diff --git a/docs/user-guide/providers/aws/boto3-configuration.mdx b/docs/user-guide/providers/aws/boto3-configuration.mdx index 83d01d5e80..d4e348b2b7 100644 --- a/docs/user-guide/providers/aws/boto3-configuration.mdx +++ b/docs/user-guide/providers/aws/boto3-configuration.mdx @@ -1,14 +1,39 @@ --- -title: "Boto3 Retrier Configuration in Prowler" +title: "Boto3 Retrier and Timeout Configuration in Prowler" --- +import { VersionBadge } from "/snippets/version-badge.mdx" + Prowler's AWS Provider leverages Boto3's [Standard](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/retries.html) retry mode to automatically retry client calls to AWS services when encountering errors or exceptions. +## Timeout Configuration + + + +Every AWS API call is bounded by two timeouts: + +- Connect timeout: seconds to wait to establish a connection (TCP, proxy tunnel and TLS handshake) to the AWS endpoint. Prowler's default is 10 seconds, configurable via `--aws-connect-timeout 5`. +- Read timeout: seconds to wait for a response once connected. Prowler's default is 60 seconds, configurable via `--aws-read-timeout 30`. + +Both timeouts can also be set through environment variables, which is the way to tune them in Prowler Cloud and other deployments without a CLI: + +```console +export PROWLER_AWS_BOTO3_CONNECT_TIMEOUT=5 +export PROWLER_AWS_BOTO3_READ_TIMEOUT=30 +``` + +CLI flags take precedence over the environment variables. Prowler sets both timeouts explicitly, so `AWS_DEFAULTS_MODE` and a `connect_timeout` in `~/.aws/config` are ignored; use the flag or the environment variable instead. + + +Boto3 defaults both timeouts to 60 seconds. In networks with restricted egress (for example VPC endpoints for a subset of services, GovCloud or private deployments), every AWS service without a reachable endpoint used to cost up to 4 attempts × 60 seconds (the first call plus the 3 retries) for each region. Prowler lowers the connect timeout to 10 seconds so unreachable endpoints fail fast; lower it further together with `--aws-retries-max-attempts 0`, which disables retries and leaves a single attempt per call, if a scan still spends most of its time waiting on unreachable services. + + + ## Retry Behavior Overview Boto3's Standard retry mode includes the following mechanisms: -- Maximum Retry Attempts: Default value set to 3, configurable via the `--aws-retries-max-attempts 5` argument. +- Maximum Retry Attempts: Default value set to 3, configurable via the `--aws-retries-max-attempts 5` argument. `0` disables retries. - Expanded Error Handling: Retries occur for a comprehensive set of errors. diff --git a/prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md b/prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md new file mode 100644 index 0000000000..a204443b2a --- /dev/null +++ b/prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md @@ -0,0 +1 @@ +AWS provider default Boto3 connect timeout lowered from 60 to 10 seconds, so scans in restricted-egress networks (VPC endpoints for a subset of services, GovCloud, private deployments) no longer spend 4 minutes per region on every service whose endpoint is unreachable diff --git a/prowler/changelog.d/aws-boto3-timeouts.added.md b/prowler/changelog.d/aws-boto3-timeouts.added.md new file mode 100644 index 0000000000..df5d6e4f2b --- /dev/null +++ b/prowler/changelog.d/aws-boto3-timeouts.added.md @@ -0,0 +1 @@ +`--aws-connect-timeout` and `--aws-read-timeout` CLI flags, plus `PROWLER_AWS_BOTO3_CONNECT_TIMEOUT` and `PROWLER_AWS_BOTO3_READ_TIMEOUT` environment variables, to bound how long each AWS API call waits for an endpoint diff --git a/prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md b/prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md new file mode 100644 index 0000000000..8eb2ad9e07 --- /dev/null +++ b/prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md @@ -0,0 +1 @@ +`--aws-retries-max-attempts 0` now disables Boto3 retries instead of being silently ignored in favour of the default of 3 diff --git a/prowler/providers/aws/aws_provider.py b/prowler/providers/aws/aws_provider.py index d0ca3b98ee..07e3ecab89 100644 --- a/prowler/providers/aws/aws_provider.py +++ b/prowler/providers/aws/aws_provider.py @@ -126,6 +126,8 @@ class AwsProvider(Provider): aws_access_key_id: str = None, aws_secret_access_key: str = None, aws_session_token: Optional[str] = None, + connect_timeout: Optional[int] = None, + read_timeout: Optional[int] = None, ): """ Initializes the AWS provider. @@ -155,6 +157,8 @@ class AwsProvider(Provider): - aws_access_key_id: The AWS access key ID. - aws_secret_access_key: The AWS secret access key. - aws_session_token: The AWS session token, optional. + - connect_timeout: Seconds to wait to establish a connection to an AWS endpoint. + - read_timeout: Seconds to wait for a response from an AWS endpoint. Raises: - ArgumentTypeError: If the input MFA ARN is invalid. @@ -229,7 +233,9 @@ class AwsProvider(Provider): # TODO: Use AwsSetUpSession ????? # Configure the initial AWS Session using the local credentials: profile or environment variables - session_config = self.set_session_config(retries_max_attempts) + session_config = self.set_session_config( + retries_max_attempts, connect_timeout, read_timeout + ) aws_session = self.setup_session( mfa=mfa, profile=profile, @@ -1165,26 +1171,35 @@ class AwsProvider(Provider): return AWSMFAInfo(arn=mfa_ARN, totp=mfa_TOTP) @staticmethod - def set_session_config(retries_max_attempts: int) -> Config: + def set_session_config( + retries_max_attempts: int, + connect_timeout: Optional[int] = None, + read_timeout: Optional[int] = None, + ) -> Config: """ - set_session_config returns a botocore Config object with the Prowler user agent and the default retrier configuration if nothing is passed as argument + set_session_config returns a botocore Config object with the Prowler user agent and the default retrier and timeout configuration if nothing is passed as argument Args: - retries_max_attempts: The maximum number of retries for the standard retrier config + - connect_timeout: Seconds to wait to establish a connection to an AWS endpoint + - read_timeout: Seconds to wait for a response from an AWS endpoint Returns: - Config: The botocore Config object """ default_session_config = get_default_session_config() - if retries_max_attempts: - default_session_config = default_session_config.merge( - Config( - retries={ - "max_attempts": retries_max_attempts, - "mode": "standard", - }, - ) - ) + overrides = {} + if retries_max_attempts is not None: + overrides["retries"] = { + "max_attempts": retries_max_attempts, + "mode": "standard", + } + if connect_timeout: + overrides["connect_timeout"] = connect_timeout + if read_timeout: + overrides["read_timeout"] = read_timeout + if overrides: + default_session_config = default_session_config.merge(Config(**overrides)) return default_session_config diff --git a/prowler/providers/aws/config.py b/prowler/providers/aws/config.py index ea55d1a314..ed2ca503d0 100644 --- a/prowler/providers/aws/config.py +++ b/prowler/providers/aws/config.py @@ -2,14 +2,39 @@ import os from botocore.config import Config +from prowler.providers.aws.exceptions.exceptions import AWSInvalidBoto3TimeoutError + AWS_STS_GLOBAL_ENDPOINT_REGION = "us-east-1" AWS_REGION_US_EAST_1 = "us-east-1" BOTO3_USER_AGENT_EXTRA = os.getenv("PROWLER_AWS_BOTO3_USER_AGENT_EXTRA", "APN_1826889") +BOTO3_RETRIES_MAX_ATTEMPTS = 3 +# botocore defaults both to 60s +BOTO3_CONNECT_TIMEOUT = 10 +BOTO3_READ_TIMEOUT = 60 ROLE_SESSION_NAME = "ProwlerAssessmentSession" +def get_boto3_timeout_from_env(name: str, default: int) -> int: + """Positive integer seconds read from the environment, or default when unset.""" + raw = os.getenv(name, "").strip() + if not raw: + return default + if not raw.isdecimal() or int(raw) == 0: + raise AWSInvalidBoto3TimeoutError( + file=os.path.basename(__file__), + message=f"{name} must be a positive integer number of seconds, got {raw!r}", + ) + return int(raw) + + def get_default_session_config() -> Config: return Config( user_agent_extra=BOTO3_USER_AGENT_EXTRA, - retries={"max_attempts": 3, "mode": "standard"}, + retries={"max_attempts": BOTO3_RETRIES_MAX_ATTEMPTS, "mode": "standard"}, + connect_timeout=get_boto3_timeout_from_env( + "PROWLER_AWS_BOTO3_CONNECT_TIMEOUT", BOTO3_CONNECT_TIMEOUT + ), + read_timeout=get_boto3_timeout_from_env( + "PROWLER_AWS_BOTO3_READ_TIMEOUT", BOTO3_READ_TIMEOUT + ), ) diff --git a/prowler/providers/aws/exceptions/exceptions.py b/prowler/providers/aws/exceptions/exceptions.py index 4ea3d5e177..089e0d99c7 100644 --- a/prowler/providers/aws/exceptions/exceptions.py +++ b/prowler/providers/aws/exceptions/exceptions.py @@ -78,6 +78,10 @@ class AWSBaseException(ProwlerException): "message": "The provided AWS partition is invalid", "remediation": "Check the provided AWS partition and ensure it is valid.", }, + (1918, "AWSInvalidBoto3TimeoutError"): { + "message": "The Boto3 timeout configured through the environment is invalid", + "remediation": "Set PROWLER_AWS_BOTO3_CONNECT_TIMEOUT and PROWLER_AWS_BOTO3_READ_TIMEOUT to a positive integer number of seconds.", + }, } def __init__(self, code, file=None, original_exception=None, message=None): @@ -231,3 +235,12 @@ class AWSInvalidPartitionError(AWSBaseException): super().__init__( 1917, file=file, original_exception=original_exception, message=message ) + + +class AWSInvalidBoto3TimeoutError(AWSBaseException): + """Boto3 timeout configured through the environment is not a positive integer.""" + + def __init__(self, file=None, original_exception=None, message=None): + super().__init__( + 1918, file=file, original_exception=original_exception, message=message + ) diff --git a/prowler/providers/aws/lib/arguments/arguments.py b/prowler/providers/aws/lib/arguments/arguments.py index 2d1632422b..84f3b4adfa 100644 --- a/prowler/providers/aws/lib/arguments/arguments.py +++ b/prowler/providers/aws/lib/arguments/arguments.py @@ -156,7 +156,21 @@ def init_parser(self): nargs="?", default=None, type=int, - help="Set the maximum attemps for the Boto3 standard retrier config (Default: 3)", + help="Set the maximum retries for the Boto3 standard retrier config, 0 disables retries (Default: 3)", + ) + boto3_config_subparser.add_argument( + "--aws-connect-timeout", + nargs="?", + default=None, + type=validate_timeout, + help="Seconds to wait to establish a connection (TCP, proxy tunnel and TLS) to an AWS endpoint before retrying (Default: 10)", + ) + boto3_config_subparser.add_argument( + "--aws-read-timeout", + nargs="?", + default=None, + type=validate_timeout, + help="Seconds to wait for a response from an AWS endpoint before retrying (Default: 60)", ) # Scan Unused Services @@ -190,6 +204,13 @@ def validate_session_duration(session_duration: int) -> int: return duration +def validate_timeout(value: str) -> int: + """validate_timeout validates that the input is a whole number of seconds greater than zero""" + if not value.isdecimal() or int(value) == 0: + raise ArgumentTypeError(f"{value} is not a positive integer") + return int(value) + + def validate_role_session_name(session_name) -> str: """ Validates that the role session name is valid. diff --git a/prowler/providers/aws/lib/session/aws_set_up_session.py b/prowler/providers/aws/lib/session/aws_set_up_session.py index 3189400040..8f0b4130ca 100644 --- a/prowler/providers/aws/lib/session/aws_set_up_session.py +++ b/prowler/providers/aws/lib/session/aws_set_up_session.py @@ -42,6 +42,8 @@ class AwsSetUpSession: aws_session_token: Optional[str] = None, retries_max_attempts: int = 3, regions: set = set(), + connect_timeout: Optional[int] = None, + read_timeout: Optional[int] = None, ) -> None: """ The constructor for the AwsSetUpSession class. @@ -58,6 +60,8 @@ class AwsSetUpSession: - aws_session_token: The AWS session token, optional. - retries_max_attempts: The maximum number of retries for the AWS client. - regions: A set of regions to audit. + - connect_timeout: Seconds to wait to establish a connection to an AWS endpoint. + - read_timeout: Seconds to wait for a response from an AWS endpoint. Returns: @@ -73,7 +77,9 @@ class AwsSetUpSession: aws_access_key_id=aws_access_key_id, aws_secret_access_key=aws_secret_access_key, ) - session_config = AwsProvider.set_session_config(retries_max_attempts) + session_config = AwsProvider.set_session_config( + retries_max_attempts, connect_timeout, read_timeout + ) aws_session = AwsProvider.setup_session( mfa=mfa, profile=profile, diff --git a/prowler/providers/common/provider.py b/prowler/providers/common/provider.py index 2e81bad121..7e23b8de7f 100644 --- a/prowler/providers/common/provider.py +++ b/prowler/providers/common/provider.py @@ -382,6 +382,8 @@ class Provider(ABC): ) provider_class( retries_max_attempts=arguments.aws_retries_max_attempts, + connect_timeout=arguments.aws_connect_timeout, + read_timeout=arguments.aws_read_timeout, role_arn=arguments.role, session_duration=arguments.session_duration, external_id=arguments.external_id, diff --git a/tests/lib/cli/parser_test.py b/tests/lib/cli/parser_test.py index da16f437b5..a811186b3b 100644 --- a/tests/lib/cli/parser_test.py +++ b/tests/lib/cli/parser_test.py @@ -1152,6 +1152,35 @@ class Test_Parser: parsed = self.parser.parse(command) assert parsed.aws_retries_max_attempts == int(max_retries) + def test_aws_parser_retries_max_attempts_zero(self): + command = [prowler_command, "--aws-retries-max-attempts", "0"] + parsed = self.parser.parse(command) + assert parsed.aws_retries_max_attempts == 0 + + def test_aws_parser_timeouts_default_to_none(self): + parsed = self.parser.parse([prowler_command]) + assert parsed.aws_connect_timeout is None + assert parsed.aws_read_timeout is None + + @pytest.mark.parametrize( + "argument, attribute", + [ + ("--aws-connect-timeout", "aws_connect_timeout"), + ("--aws-read-timeout", "aws_read_timeout"), + ], + ) + def test_aws_parser_timeouts(self, argument, attribute): + timeout = "5" + command = [prowler_command, argument, timeout] + parsed = self.parser.parse(command) + assert getattr(parsed, attribute) == int(timeout) + + @pytest.mark.parametrize("value", ["0", "-1", "abc"]) + def test_aws_parser_connect_timeout_rejects_non_positive(self, value): + command = [prowler_command, "--aws-connect-timeout", value] + with pytest.raises(SystemExit): + self.parser.parse(command) + def test_aws_parser_scan_unused_services(self): argument = "--scan-unused-services" command = [prowler_command, argument] diff --git a/tests/providers/aws/aws_provider_test.py b/tests/providers/aws/aws_provider_test.py index 7ce61b6862..cd8bb4f049 100644 --- a/tests/providers/aws/aws_provider_test.py +++ b/tests/providers/aws/aws_provider_test.py @@ -24,19 +24,24 @@ from prowler.providers.aws.aws_provider import ( ) from prowler.providers.aws.config import ( AWS_STS_GLOBAL_ENDPOINT_REGION, + BOTO3_CONNECT_TIMEOUT, + BOTO3_READ_TIMEOUT, BOTO3_USER_AGENT_EXTRA, ROLE_SESSION_NAME, + get_boto3_timeout_from_env, get_default_session_config, ) from prowler.providers.aws.exceptions.exceptions import ( AWSArgumentTypeValidationError, AWSIAMRoleARNInvalidResourceTypeError, + AWSInvalidBoto3TimeoutError, AWSInvalidPartitionError, AWSInvalidProviderIdError, AWSNoCredentialsError, ) from prowler.providers.aws.lib.arn.models import ARN from prowler.providers.aws.lib.mutelist.mutelist import AWSMutelist +from prowler.providers.aws.lib.session.aws_set_up_session import AwsSetUpSession from prowler.providers.aws.models import ( AWSAssumeRoleInfo, AWSCallerIdentity, @@ -2735,6 +2740,8 @@ aws: assert session_config.user_agent_extra == BOTO3_USER_AGENT_EXTRA assert session_config.retries == {"max_attempts": 3, "mode": "standard"} + assert session_config.connect_timeout == BOTO3_CONNECT_TIMEOUT + assert session_config.read_timeout == BOTO3_READ_TIMEOUT @mock_aws def test_set_session_config_10_max_attempts(self): @@ -2743,12 +2750,93 @@ aws: assert session_config.user_agent_extra == BOTO3_USER_AGENT_EXTRA assert session_config.retries == {"max_attempts": 10, "mode": "standard"} + assert session_config.connect_timeout == BOTO3_CONNECT_TIMEOUT + assert session_config.read_timeout == BOTO3_READ_TIMEOUT + + def test_set_session_config_0_max_attempts_disables_retries(self): + session_config = AwsProvider.set_session_config(0) + + assert session_config.retries == {"max_attempts": 0, "mode": "standard"} + + @mock_aws + def test_aws_provider_0_max_attempts_reaches_clients(self): + aws_provider = AwsProvider(retries_max_attempts=0) + client = aws_provider.session.current_session.client( + "ec2", region_name=AWS_REGION_US_EAST_1 + ) + + # botocore rewrites max_attempts into total_max_attempts (retries + 1) + assert client.meta.config.retries["total_max_attempts"] == 1 + + def test_set_session_config_timeouts(self): + session_config = AwsProvider.set_session_config( + None, connect_timeout=2, read_timeout=15 + ) + + assert session_config.retries == {"max_attempts": 3, "mode": "standard"} + assert session_config.connect_timeout == 2 + assert session_config.read_timeout == 15 + + @mock_aws + def test_aws_provider_timeouts_reach_session_config(self): + aws_provider = AwsProvider(connect_timeout=2, read_timeout=15) + + assert aws_provider.session.session_config.connect_timeout == 2 + assert aws_provider.session.session_config.read_timeout == 15 + + @mock_aws + def test_aws_set_up_session_forwards_timeouts(self): + aws_session = AwsSetUpSession( + aws_access_key_id="testing", + aws_secret_access_key="testing", + connect_timeout=2, + read_timeout=15, + ) + + assert aws_session._session.session_config.connect_timeout == 2 + assert aws_session._session.session_config.read_timeout == 15 def test_get_default_session_config(self): config = get_default_session_config() assert config.user_agent_extra == BOTO3_USER_AGENT_EXTRA assert config.retries == {"max_attempts": 3, "mode": "standard"} + assert config.connect_timeout == BOTO3_CONNECT_TIMEOUT + assert config.read_timeout == BOTO3_READ_TIMEOUT + + def test_get_default_session_config_timeouts_from_env(self): + with mock.patch.dict( + os.environ, + { + "PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": "3", + "PROWLER_AWS_BOTO3_READ_TIMEOUT": "20", + }, + ): + config = get_default_session_config() + + assert config.connect_timeout == 3 + assert config.read_timeout == 20 + + def test_set_session_config_argument_overrides_env_timeouts(self): + with mock.patch.dict(os.environ, {"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": "3"}): + config = AwsProvider.set_session_config(None, connect_timeout=7) + + assert config.connect_timeout == 7 + + @pytest.mark.parametrize("raw", ["0", "-5", "ten", "1.5"]) + def test_get_boto3_timeout_from_env_rejects_non_positive_integers(self, raw): + with mock.patch.dict(os.environ, {"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": raw}): + with raises( + AWSInvalidBoto3TimeoutError, match="PROWLER_AWS_BOTO3_CONNECT_TIMEOUT" + ): + get_boto3_timeout_from_env("PROWLER_AWS_BOTO3_CONNECT_TIMEOUT", 10) + + def test_get_boto3_timeout_from_env_blank_falls_back_to_default(self): + with mock.patch.dict(os.environ, {"PROWLER_AWS_BOTO3_CONNECT_TIMEOUT": " "}): + assert ( + get_boto3_timeout_from_env("PROWLER_AWS_BOTO3_CONNECT_TIMEOUT", 10) + == 10 + ) @mock_aws @patch( From f9c02da90a41f5b00a06c61b7fbfa6006ed4c33b Mon Sep 17 00:00:00 2001 From: StylusFrost <43682773+StylusFrost@users.noreply.github.com> Date: Thu, 10 Sep 2026 17:15:13 +0200 Subject: [PATCH 50/77] feat(aws): support the ISO partitions for region resolution and scanning (#12759) Co-authored-by: pedrooot --- .../sdk-refresh-aws-services-regions.yml | 5 +- .../changelog.d/aws-iso-partitions.added.md | 1 + .../changelog.d/aws-iso-partitions.fixed.md | 1 + .../aws-regional-clients-empty-dict.fixed.md | 1 + ...service-regions-unknown-partition.fixed.md | 1 + prowler/providers/aws/aws_provider.py | 27 +- .../providers/aws/aws_regions_by_service.json | 2621 +++++++++++++++++ tests/providers/aws/aws_provider_test.py | 119 +- tests/providers/aws/utils.py | 5 +- util/update_aws_services_regions.py | 364 ++- 10 files changed, 3045 insertions(+), 100 deletions(-) create mode 100644 prowler/changelog.d/aws-iso-partitions.added.md create mode 100644 prowler/changelog.d/aws-iso-partitions.fixed.md create mode 100644 prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md create mode 100644 prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md diff --git a/.github/workflows/sdk-refresh-aws-services-regions.yml b/.github/workflows/sdk-refresh-aws-services-regions.yml index 5a38858247..075852c6a6 100644 --- a/.github/workflows/sdk-refresh-aws-services-regions.yml +++ b/.github/workflows/sdk-refresh-aws-services-regions.yml @@ -44,7 +44,10 @@ jobs: cache: 'pip' - name: Install dependencies - run: pip install boto3 + # Pinned to the versions in pyproject.toml: the ISO partitions region + # data comes from the endpoints.json bundled with botocore, so the + # botocore version is itself a data source and must be deterministic + run: pip install boto3==1.40.61 botocore==1.40.61 - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1 diff --git a/prowler/changelog.d/aws-iso-partitions.added.md b/prowler/changelog.d/aws-iso-partitions.added.md new file mode 100644 index 0000000000..41282ea353 --- /dev/null +++ b/prowler/changelog.d/aws-iso-partitions.added.md @@ -0,0 +1 @@ +AWS ISO partitions (`aws-iso`, `aws-iso-b`, `aws-iso-e` and `aws-iso-f`) to the AWS service region matrix, generated from the endpoints data bundled with botocore diff --git a/prowler/changelog.d/aws-iso-partitions.fixed.md b/prowler/changelog.d/aws-iso-partitions.fixed.md new file mode 100644 index 0000000000..c3424d51ba --- /dev/null +++ b/prowler/changelog.d/aws-iso-partitions.fixed.md @@ -0,0 +1 @@ +`AwsProvider.get_global_region()` now returns a real region for each ISO partition instead of the `aws-iso-global` pseudo endpoint, which collapsed the four partitions into one answer diff --git a/prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md b/prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md new file mode 100644 index 0000000000..bd5f7798ac --- /dev/null +++ b/prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md @@ -0,0 +1 @@ +`AwsProvider.generate_regional_clients()` now returns an empty dict instead of `None` when the regional clients cannot be built, a failure that surfaced later as `AttributeError: 'NoneType' object has no attribute 'values'` diff --git a/prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md b/prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md new file mode 100644 index 0000000000..881ce2c94b --- /dev/null +++ b/prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md @@ -0,0 +1 @@ +`AwsProvider.get_available_aws_service_regions()` now returns an empty set for an unknown service or partition instead of raising `KeyError`, so a service unavailable in the audited partition is skipped diff --git a/prowler/providers/aws/aws_provider.py b/prowler/providers/aws/aws_provider.py index 07e3ecab89..e204318593 100644 --- a/prowler/providers/aws/aws_provider.py +++ b/prowler/providers/aws/aws_provider.py @@ -921,6 +921,9 @@ class AwsProvider(Provider): logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + # Return an empty dict, as promised by the signature, so the service + # is simply not scanned instead of the callers failing later on a None + return {} @staticmethod def get_available_aws_service_regions( @@ -936,9 +939,13 @@ class AwsProvider(Provider): Returns: - A set of strings representing the available regions for the given service and partition. + A service or a partition not present in the regions file yields an empty set, the same + outcome as a service explicitly recorded as unavailable in the partition. """ data = read_aws_regions_file() - json_regions = set(data["services"][service]["regions"][partition]) + json_regions = set( + data["services"].get(service, {}).get("regions", {}).get(partition, []) + ) if audited_regions: # Get common regions between input and json regions = json_regions.intersection(audited_regions) @@ -1145,16 +1152,14 @@ class AwsProvider(Provider): Example: global_region = get_global_region()a """ - global_region = "us-east-1" - if self._identity.partition == "aws-cn": - global_region = "cn-north-1" - elif self._identity.partition == "aws-eusc": - global_region = "eusc-de-east-1" - elif self._identity.partition == "aws-us-gov": - global_region = "us-gov-east-1" - elif "aws-iso" in self._identity.partition: - global_region = "aws-iso-global" - return global_region + # The first region of the partition is the one of its global STS endpoint, + # which is always a real region, never a pseudo endpoint like "aws-iso-global" + partition_regions = get_botocore_partition_regions().get( + self._identity.partition + ) + if partition_regions: + return partition_regions[0] + return "us-east-1" @staticmethod def input_role_mfa_token_and_code() -> AWSMFAInfo: diff --git a/prowler/providers/aws/aws_regions_by_service.json b/prowler/providers/aws/aws_regions_by_service.json index bd66643d27..bb51556b78 100644 --- a/prowler/providers/aws/aws_regions_by_service.json +++ b/prowler/providers/aws/aws_regions_by_service.json @@ -10,6 +10,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -58,6 +62,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -102,6 +115,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -150,6 +167,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -201,6 +227,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -221,6 +256,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -238,6 +277,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -268,6 +311,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -292,6 +339,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -323,6 +374,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -351,6 +406,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -379,6 +438,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -427,6 +490,17 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -461,6 +535,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -510,6 +588,17 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -561,6 +650,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -612,6 +716,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -640,6 +759,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -659,6 +782,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -693,6 +820,21 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -737,6 +879,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -750,6 +896,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -787,6 +937,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -807,6 +961,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -834,6 +992,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -880,6 +1042,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -923,6 +1089,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -974,6 +1144,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1022,6 +1207,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1073,6 +1262,19 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1097,6 +1299,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1118,6 +1324,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1166,6 +1376,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1217,6 +1431,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1232,6 +1461,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1250,6 +1483,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1298,6 +1535,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1319,6 +1560,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1337,6 +1582,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1385,6 +1634,18 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1418,6 +1679,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1469,6 +1734,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1484,6 +1764,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1496,6 +1780,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1506,6 +1794,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1550,6 +1842,12 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1576,6 +1874,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -1606,6 +1908,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1626,6 +1932,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -1657,6 +1967,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1670,6 +1984,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1680,6 +1998,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1694,6 +2016,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1711,6 +2037,18 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -1754,6 +2092,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1781,6 +2123,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1812,6 +2158,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1826,6 +2176,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1845,6 +2199,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1866,6 +2224,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -1880,6 +2242,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1899,6 +2265,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1919,6 +2289,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1939,6 +2313,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -1970,6 +2348,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2018,6 +2400,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2039,6 +2436,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -2071,6 +2472,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2104,6 +2509,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2155,6 +2564,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2204,6 +2628,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2245,6 +2673,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2267,6 +2699,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2307,6 +2743,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2358,6 +2798,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2385,6 +2840,15 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -2433,6 +2897,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2458,6 +2937,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2501,6 +2984,18 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2515,6 +3010,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2552,6 +3051,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2581,6 +3084,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1" ] @@ -2631,6 +3138,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2653,6 +3175,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2672,6 +3198,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2714,6 +3244,13 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2743,6 +3280,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1" ] @@ -2772,6 +3313,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2782,6 +3327,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2827,6 +3376,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2877,6 +3430,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2925,6 +3482,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -2948,6 +3509,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -2969,6 +3534,15 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-west-1" ] @@ -2987,6 +3561,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -3031,6 +3609,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3060,6 +3647,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3108,6 +3699,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3130,6 +3736,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -3151,6 +3761,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3170,6 +3784,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3189,6 +3807,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3201,6 +3823,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3220,6 +3846,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -3267,6 +3897,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3315,6 +3949,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3330,6 +3968,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -3344,6 +3990,16 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -3363,6 +4019,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3394,6 +4054,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -3416,6 +4080,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3430,6 +4098,12 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3478,6 +4152,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3509,6 +4192,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3536,6 +4223,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3555,6 +4246,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3585,6 +4280,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3598,6 +4297,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3623,6 +4326,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3671,6 +4378,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3690,6 +4412,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -3738,6 +4464,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3789,6 +4530,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3836,6 +4592,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3884,6 +4655,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3935,6 +4710,20 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -3967,6 +4756,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -4015,6 +4808,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4066,6 +4874,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4117,6 +4940,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4168,6 +5006,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4219,6 +5072,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4233,6 +5101,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -4281,6 +5153,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4332,6 +5219,20 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4383,6 +5284,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4429,6 +5345,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4480,6 +5400,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4527,6 +5462,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4578,6 +5517,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4629,6 +5583,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4646,6 +5615,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -4694,6 +5667,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4736,6 +5724,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4787,6 +5779,12 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4811,6 +5809,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -4859,6 +5861,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4910,6 +5927,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4961,6 +5982,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -4995,6 +6031,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5043,6 +6083,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5065,6 +6109,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5084,6 +6132,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5098,6 +6150,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5146,6 +6202,20 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5182,6 +6252,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5231,6 +6305,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5253,6 +6331,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5272,6 +6354,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5287,6 +6373,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5317,6 +6407,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5365,6 +6459,18 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5416,6 +6522,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5467,6 +6577,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5518,6 +6632,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5569,6 +6687,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5607,6 +6729,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5641,6 +6767,15 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5687,6 +6822,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5735,6 +6874,19 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5757,6 +6909,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5785,6 +6941,10 @@ "cn-north-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5809,6 +6969,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -5857,6 +7021,17 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5876,6 +7051,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5927,6 +7110,19 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -5978,6 +7174,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6029,6 +7229,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6080,6 +7284,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6104,6 +7312,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6152,6 +7364,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6200,6 +7416,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6239,6 +7459,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6249,6 +7473,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6284,6 +7512,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6322,6 +7554,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6358,6 +7594,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6373,6 +7613,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6386,6 +7630,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6418,6 +7666,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6456,6 +7708,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6471,6 +7727,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6506,6 +7766,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6531,6 +7795,10 @@ "cn-north-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -6541,6 +7809,10 @@ "aws": [], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6561,6 +7833,10 @@ "cn-north-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -6579,6 +7855,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6595,6 +7875,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6611,6 +7895,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6627,6 +7915,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6675,6 +7967,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6724,6 +8020,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6746,6 +8046,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -6766,6 +8070,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -6814,6 +8122,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6865,6 +8188,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6899,6 +8230,12 @@ "cn-north-1" ], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -6950,6 +8287,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7001,6 +8353,19 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7052,6 +8417,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7100,6 +8480,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7142,6 +8526,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7165,6 +8553,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -7187,6 +8579,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -7237,6 +8633,20 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7285,6 +8695,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7330,6 +8744,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7361,6 +8779,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7409,6 +8831,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7424,6 +8861,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7451,6 +8892,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7481,6 +8926,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7495,6 +8944,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7526,6 +8979,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7557,6 +9014,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7572,6 +9033,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -7584,6 +9049,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7615,6 +9084,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7666,6 +9139,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7681,6 +9158,12 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7691,6 +9174,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7705,6 +9192,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7715,6 +9206,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7750,6 +9245,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -7785,6 +9284,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7817,6 +9320,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -7848,6 +9355,14 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7875,6 +9390,14 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7904,6 +9427,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7934,6 +9461,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7952,6 +9483,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7970,6 +9505,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -7999,6 +9538,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8013,6 +9556,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8044,6 +9591,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8088,6 +9639,12 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8107,6 +9664,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8150,6 +9711,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8179,6 +9744,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8195,6 +9764,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8211,6 +9784,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8223,6 +9800,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8271,6 +9852,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8284,6 +9869,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8327,6 +9916,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8368,6 +9961,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8411,6 +10008,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8448,6 +10060,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8496,6 +10112,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8525,6 +10149,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8568,6 +10196,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8608,6 +10240,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8651,6 +10287,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8663,6 +10303,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8673,6 +10317,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8721,6 +10369,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8765,6 +10428,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8795,6 +10462,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8814,6 +10485,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8862,6 +10537,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8896,6 +10586,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -8917,6 +10611,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8935,6 +10633,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -8983,6 +10685,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9012,6 +10729,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9050,6 +10771,14 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9063,6 +10792,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9073,6 +10806,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9083,6 +10820,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9108,6 +10849,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9153,6 +10898,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9197,6 +10946,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9225,6 +10978,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9248,6 +11005,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9296,6 +11057,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9320,6 +11096,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -9337,6 +11117,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9352,6 +11136,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9394,6 +11182,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9435,6 +11227,15 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -9472,6 +11273,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -9490,6 +11295,18 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -9538,6 +11355,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9561,6 +11382,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9572,6 +11397,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9585,6 +11414,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9596,6 +11429,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9633,6 +11470,13 @@ "cn-north-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9684,6 +11528,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9735,6 +11594,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9786,6 +11660,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9812,6 +11701,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9822,6 +11715,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -9870,6 +11767,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9921,6 +11833,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -9971,6 +11887,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10001,6 +11926,13 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-west-1" ] @@ -10019,6 +11951,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10048,6 +11984,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10097,6 +12037,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10148,6 +12092,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10199,6 +12158,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10250,6 +12224,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10290,6 +12268,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10341,6 +12323,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10392,6 +12389,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10431,6 +12432,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10441,6 +12446,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10451,6 +12460,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10497,6 +12510,15 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10548,6 +12570,20 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10566,6 +12602,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10609,6 +12649,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10660,6 +12704,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10706,6 +12765,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10741,6 +12809,14 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10789,6 +12865,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10840,6 +12920,17 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10880,6 +12971,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10890,6 +12985,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -10931,6 +13030,17 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [] } }, @@ -10979,6 +13089,17 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -10990,6 +13111,10 @@ "aws": [], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11035,6 +13160,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11086,6 +13220,20 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11126,6 +13274,15 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11146,6 +13303,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11194,6 +13355,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11231,6 +13407,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11279,6 +13459,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11308,6 +13497,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11341,6 +13534,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11392,6 +13589,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11437,6 +13649,12 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11478,6 +13696,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11529,6 +13751,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11570,6 +13807,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11611,6 +13852,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11655,6 +13900,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11689,6 +13938,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11740,6 +13993,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11755,6 +14012,10 @@ "cn-north-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -11772,6 +14033,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11798,6 +14063,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11830,6 +14099,15 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11857,6 +14135,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11905,6 +14187,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -11951,6 +14248,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -11999,6 +14300,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12050,6 +14366,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12078,6 +14409,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12103,6 +14438,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12128,6 +14467,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12165,6 +14508,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12213,6 +14560,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12264,6 +14615,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12315,6 +14681,15 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12366,6 +14741,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12417,6 +14807,16 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12432,6 +14832,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12443,6 +14847,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12491,6 +14899,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12542,6 +14965,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12557,6 +14995,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12580,6 +15022,15 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12599,6 +15050,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12616,6 +15071,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -12650,6 +15109,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12667,6 +15130,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -12686,6 +15153,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -12707,6 +15178,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12739,6 +15214,15 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12790,6 +15274,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12841,6 +15329,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12869,6 +15361,15 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-west-1" ] @@ -12919,6 +15420,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -12932,6 +15441,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -12959,6 +15472,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13008,6 +15525,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13044,6 +15565,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13064,6 +15589,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13112,6 +15641,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13154,6 +15687,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13199,6 +15736,10 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13250,6 +15791,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13293,6 +15842,10 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13344,6 +15897,14 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13374,6 +15935,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13404,6 +15969,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13426,6 +15995,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-west-1" ] @@ -13447,6 +16020,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13462,6 +16039,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13474,6 +16055,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13486,6 +16071,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13514,6 +16103,15 @@ "cn-northwest-1" ], "aws-eusc": [], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1" + ], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" @@ -13532,6 +16130,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13551,6 +16153,10 @@ ], "aws-cn": [], "aws-eusc": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], "aws-us-gov": [] } }, @@ -13599,6 +16205,21 @@ "aws-eusc": [ "eusc-de-east-1" ], + "aws-iso": [ + "us-iso-east-1", + "us-iso-west-1" + ], + "aws-iso-b": [ + "us-isob-east-1", + "us-isob-west-1" + ], + "aws-iso-e": [ + "eu-isoe-west-1" + ], + "aws-iso-f": [ + "us-isof-east-1", + "us-isof-south-1" + ], "aws-us-gov": [ "us-gov-east-1", "us-gov-west-1" diff --git a/tests/providers/aws/aws_provider_test.py b/tests/providers/aws/aws_provider_test.py index cd8bb4f049..f899706453 100644 --- a/tests/providers/aws/aws_provider_test.py +++ b/tests/providers/aws/aws_provider_test.py @@ -59,6 +59,7 @@ from tests.providers.aws.utils import ( AWS_EUSC_PARTITION, AWS_GOV_CLOUD_ACCOUNT_ARN, AWS_GOV_CLOUD_PARTITION, + AWS_ISO_B_PARTITION, AWS_ISO_PARTITION, AWS_REGION_CN_NORTH_1, AWS_REGION_CN_NORTHWEST_1, @@ -67,7 +68,9 @@ from tests.providers.aws.utils import ( AWS_REGION_EUSC_DE_EAST_1, AWS_REGION_GOV_CLOUD_US_EAST_1, AWS_REGION_GOV_CLOUD_US_WEST_1, - AWS_REGION_ISO_GLOBAL, + AWS_REGION_ISO_B_EAST_1, + AWS_REGION_ISO_EAST_1, + AWS_REGION_ISO_WEST_1, AWS_REGION_US_EAST_1, AWS_REGION_US_EAST_2, EXAMPLE_AMI_ID, @@ -1192,6 +1195,13 @@ aws: == AWS_REGION_EU_WEST_1 ) + @mock_aws + def test_aws_get_global_region(self): + aws_provider = AwsProvider() + aws_provider._identity.partition = AWS_COMMERCIAL_PARTITION + + assert aws_provider.get_global_region() == AWS_REGION_US_EAST_1 + @mock_aws def test_aws_gov_get_global_region(self): aws_provider = AwsProvider() @@ -1211,7 +1221,21 @@ aws: aws_provider = AwsProvider() aws_provider._identity.partition = AWS_ISO_PARTITION - assert aws_provider.get_global_region() == AWS_REGION_ISO_GLOBAL + assert aws_provider.get_global_region() == AWS_REGION_ISO_EAST_1 + + @mock_aws + def test_aws_iso_b_get_global_region(self): + aws_provider = AwsProvider() + aws_provider._identity.partition = AWS_ISO_B_PARTITION + + assert aws_provider.get_global_region() == AWS_REGION_ISO_B_EAST_1 + + @mock_aws + def test_get_global_region_for_an_unknown_partition(self): + aws_provider = AwsProvider() + aws_provider._identity.partition = "aws-unknown" + + assert aws_provider.get_global_region() == AWS_REGION_US_EAST_1 @mock_aws def test_aws_eusc_get_global_region(self): @@ -1299,6 +1323,88 @@ aws: len(aws_provider.get_available_aws_service_regions("ec2", "aws")) == 17 ) + @mock_aws + def test_get_available_aws_service_regions_commercial_and_gov_cloud(self): + aws_provider = AwsProvider() + + assert AWS_REGION_US_EAST_1 in aws_provider.get_available_aws_service_regions( + "ec2", AWS_COMMERCIAL_PARTITION + ) + assert ( + AWS_REGION_GOV_CLOUD_US_EAST_1 + in aws_provider.get_available_aws_service_regions( + "ec2", AWS_GOV_CLOUD_PARTITION + ) + ) + # A service recorded as unavailable in the partition yields an empty set + assert ( + aws_provider.get_available_aws_service_regions( + "bedrock-agent", AWS_CHINA_PARTITION + ) + == set() + ) + + @mock_aws + def test_get_available_aws_service_regions_iso_partitions(self): + aws_provider = AwsProvider() + + assert aws_provider.get_available_aws_service_regions( + "ec2", AWS_ISO_PARTITION + ) == { + AWS_REGION_ISO_EAST_1, + AWS_REGION_ISO_WEST_1, + } + assert aws_provider.get_available_aws_service_regions( + "guardduty", AWS_ISO_B_PARTITION + ) == {AWS_REGION_ISO_B_EAST_1} + # Every service carries every ISO partition, empty when not available + assert ( + aws_provider.get_available_aws_service_regions( + "bedrock", AWS_ISO_B_PARTITION + ) + == set() + ) + + @mock_aws + def test_get_available_aws_service_regions_unknown_partition(self): + aws_provider = AwsProvider() + + assert ( + aws_provider.get_available_aws_service_regions("ec2", "aws-unknown") + == set() + ) + + @mock_aws + def test_get_available_aws_service_regions_unknown_service(self): + aws_provider = AwsProvider() + + assert ( + aws_provider.get_available_aws_service_regions( + "unknown-service", AWS_COMMERCIAL_PARTITION + ) + == set() + ) + + @mock_aws + def test_generate_regional_clients_service_not_in_partition(self): + aws_provider = AwsProvider() + aws_provider._identity.partition = AWS_ISO_PARTITION + + response = aws_provider.generate_regional_clients("bedrock") + + assert response == {} + + @mock_aws + def test_generate_regional_clients_returns_empty_dict_on_error(self): + aws_provider = AwsProvider() + + with patch.object( + AwsProvider, + "get_available_aws_service_regions", + side_effect=Exception("boom"), + ): + assert aws_provider.generate_regional_clients("ec2") == {} + @mock_aws def test_get_tagged_resources(self): ec2_client = client("ec2", region_name=AWS_REGION_EU_CENTRAL_1) @@ -2065,7 +2171,8 @@ aws: assert not recovered_regions def test_get_regions_all_count(self): - assert len(AwsProvider.get_regions(partition=None)) == 39 + # 34 aws + 2 aws-cn + 2 aws-us-gov + 1 aws-eusc + 7 ISO regions + assert len(AwsProvider.get_regions(partition=None)) == 46 def test_get_regions_cn_count(self): assert len(AwsProvider.get_regions("aws-cn")) == 2 @@ -2073,6 +2180,12 @@ aws: def test_get_regions_aws_count(self): assert len(AwsProvider.get_regions(partition="aws")) == 34 + def test_get_regions_iso_count(self): + assert AwsProvider.get_regions(AWS_ISO_PARTITION) == { + AWS_REGION_ISO_EAST_1, + AWS_REGION_ISO_WEST_1, + } + def test_get_all_regions(self): with patch( "prowler.providers.aws.aws_provider.read_aws_regions_file", diff --git a/tests/providers/aws/utils.py b/tests/providers/aws/utils.py index b19efd3eec..c0cbff1c10 100644 --- a/tests/providers/aws/utils.py +++ b/tests/providers/aws/utils.py @@ -21,6 +21,7 @@ AWS_GOV_CLOUD_PARTITION = "aws-us-gov" AWS_CHINA_PARTITION = "aws-cn" AWS_EUSC_PARTITION = "aws-eusc" AWS_ISO_PARTITION = "aws-iso" +AWS_ISO_B_PARTITION = "aws-iso-b" # Root AWS Account AWS_ACCOUNT_NUMBER = "123456789012" @@ -54,7 +55,9 @@ AWS_REGION_GOV_CLOUD_US_EAST_1 = "us-gov-east-1" AWS_REGION_GOV_CLOUD_US_WEST_1 = "us-gov-west-1" # Iso Regions -AWS_REGION_ISO_GLOBAL = "aws-iso-global" +AWS_REGION_ISO_EAST_1 = "us-iso-east-1" +AWS_REGION_ISO_WEST_1 = "us-iso-west-1" +AWS_REGION_ISO_B_EAST_1 = "us-isob-east-1" # European Sovereign Cloud Regions AWS_REGION_EUSC_DE_EAST_1 = "eusc-de-east-1" diff --git a/util/update_aws_services_regions.py b/util/update_aws_services_regions.py index 40be038723..d3043f50db 100644 --- a/util/update_aws_services_regions.py +++ b/util/update_aws_services_regions.py @@ -4,6 +4,7 @@ import os import sys import boto3 +from botocore.session import Session as BotocoreSession # Logging config logging.basicConfig( @@ -13,91 +14,286 @@ logging.basicConfig( level=logging.INFO, ) -regions_by_service = {"services": {}} +# AWS partitions that the SSM global-infrastructure parameters do not publish. +# Their availability comes from the endpoints.json bundled with botocore, which +# is offline data and needs neither credentials nor network access. +ISO_PARTITIONS = ("aws-iso", "aws-iso-b", "aws-iso-e", "aws-iso-f") -logging.info("Recovering AWS Regions by Service") -client = boto3.client("ssm", region_name="us-east-1") -get_parameters_by_path_paginator = client.get_paginator("get_parameters_by_path") -# Get all AWS Available Services -for page in get_parameters_by_path_paginator.paginate( - Path="/aws/service/global-infrastructure/services" -): - for service in page["Parameters"]: - regions_by_service["services"][service["Value"]] = {} - # Get all AWS Regions for the specific service - regions = {"aws": [], "aws-cn": [], "aws-eusc": [], "aws-us-gov": []} - for page in get_parameters_by_path_paginator.paginate( - Path="/aws/service/global-infrastructure/services/" - + service["Value"] - + "/regions" - ): - for region in page["Parameters"]: - if "cn" in region["Value"]: - regions["aws-cn"].append(region["Value"]) - elif "eusc" in region["Value"]: - regions["aws-eusc"].append(region["Value"]) - elif "gov" in region["Value"]: - regions["aws-us-gov"].append(region["Value"]) - else: - regions["aws"].append(region["Value"]) - # Sort regions per partition - regions["aws"] = sorted(regions["aws"]) - regions["aws-cn"] = sorted(regions["aws-cn"]) - regions["aws-eusc"] = sorted(regions["aws-eusc"]) - regions["aws-us-gov"] = sorted(regions["aws-us-gov"]) - regions_by_service["services"][service["Value"]]["regions"] = regions +# Cost Explorer: botocore keys it by its endpoint prefix "ce", while the matrix +# (and the boto3 client name) calls it "costexplorer". Explicit rename override, +# since no boto3 service model resolves the "ce" prefix. +ISO_ENDPOINT_PREFIX_RENAMES = {"ce": "costexplorer"} -# Include the regions for the subservices and the services not present -logging.info("Updating subservices and the services not present in the original matrix") -# macie2 --> macie -regions_by_service["services"]["macie2"] = regions_by_service["services"]["macie"] -# bedrock-agent is not in SSM, and has different availability than bedrock -# See: https://docs.aws.amazon.com/bedrock/latest/userguide/agents-supported.html -regions_by_service["services"]["bedrock-agent"] = { - "regions": { - "aws": [ - "ap-northeast-1", - "ap-northeast-2", - "ap-south-1", - "ap-southeast-1", - "ap-southeast-2", - "ca-central-1", - "eu-central-1", - "eu-central-2", - "eu-west-1", - "eu-west-2", - "eu-west-3", - "sa-east-1", - "us-east-1", - "us-west-2", - ], - "aws-cn": [], - "aws-eusc": [], - "aws-us-gov": [ - "us-gov-west-1", - ], +# "transcribestreaming" is the streaming endpoint of Amazon Transcribe. The +# "transcribe" prefix is already present in the same partitions with the same +# regions, so mapping it would only duplicate data. Ignoring it is a deliberate +# decision, not a resolution failure. +ISO_IGNORED_ENDPOINT_PREFIXES = {"transcribestreaming"} + +# A service whose only endpoint in a partition is the partition-wide pseudo +# endpoint (for example "aws-iso-global") gets every region of that partition, +# matching how the matrix already records iam, organizations, route53 and +# support for aws and aws-us-gov. Cost Explorer is the exception: the matrix +# records it as a single-region service (aws: us-east-1, aws-cn: cn-northwest-1), +# so it only gets the region declared in the endpoint's credentialScope. +ISO_SINGLE_REGION_PARTITION_GLOBAL_SERVICES = {"costexplorer"} + + +def get_regions_by_service_from_ssm() -> dict: + """Get the AWS services and their regions for the partitions published in + the SSM global-infrastructure parameters: aws, aws-cn, aws-eusc and + aws-us-gov. + + Returns: + dict: The AWS regions matrix, keyed by service name. + """ + regions_by_service = {"services": {}} + + logging.info("Recovering AWS Regions by Service") + client = boto3.client("ssm", region_name="us-east-1") + get_parameters_by_path_paginator = client.get_paginator("get_parameters_by_path") + # Get all AWS Available Services + for page in get_parameters_by_path_paginator.paginate( + Path="/aws/service/global-infrastructure/services" + ): + for service in page["Parameters"]: + regions_by_service["services"][service["Value"]] = {} + # Get all AWS Regions for the specific service + regions = { + "aws": [], + "aws-cn": [], + "aws-eusc": [], + "aws-us-gov": [], + "aws-iso": [], + "aws-iso-b": [], + "aws-iso-e": [], + "aws-iso-f": [], + } + for page in get_parameters_by_path_paginator.paginate( + Path="/aws/service/global-infrastructure/services/" + + service["Value"] + + "/regions" + ): + for region in page["Parameters"]: + if "cn" in region["Value"]: + regions["aws-cn"].append(region["Value"]) + elif "eusc" in region["Value"]: + regions["aws-eusc"].append(region["Value"]) + elif "gov" in region["Value"]: + regions["aws-us-gov"].append(region["Value"]) + else: + regions["aws"].append(region["Value"]) + # Sort regions per partition + regions["aws"] = sorted(regions["aws"]) + regions["aws-cn"] = sorted(regions["aws-cn"]) + regions["aws-eusc"] = sorted(regions["aws-eusc"]) + regions["aws-us-gov"] = sorted(regions["aws-us-gov"]) + regions_by_service["services"][service["Value"]]["regions"] = regions + + return regions_by_service + + +def add_subservices_and_missing_services(regions_by_service: dict) -> None: + """Include the regions for the subservices and the services not present in + the original matrix.""" + logging.info( + "Updating subservices and the services not present in the original matrix" + ) + # macie2 --> macie + regions_by_service["services"]["macie2"] = regions_by_service["services"]["macie"] + # bedrock-agent is not in SSM, and has different availability than bedrock + # See: https://docs.aws.amazon.com/bedrock/latest/userguide/agents-supported.html + regions_by_service["services"]["bedrock-agent"] = { + "regions": { + "aws": [ + "ap-northeast-1", + "ap-northeast-2", + "ap-south-1", + "ap-southeast-1", + "ap-southeast-2", + "ca-central-1", + "eu-central-1", + "eu-central-2", + "eu-west-1", + "eu-west-2", + "eu-west-3", + "sa-east-1", + "us-east-1", + "us-west-2", + ], + "aws-cn": [], + "aws-eusc": [], + "aws-us-gov": [ + "us-gov-west-1", + ], + } } -} -# cognito --> cognito-idp -regions_by_service["services"]["cognito"] = regions_by_service["services"][ - "cognito-idp" -] -# opensearch --> es -regions_by_service["services"]["opensearch"] = regions_by_service["services"]["es"] -# elbv2 --> elb -regions_by_service["services"]["elbv2"] = regions_by_service["services"]["elb"] -# wafv2 --> waf -regions_by_service["services"]["wafv2"] = regions_by_service["services"]["waf"] -# wellarchitected --> wellarchitectedtool -regions_by_service["services"]["wellarchitected"] = regions_by_service["services"][ - "wellarchitectedtool" -] -# sesv2 --> ses -regions_by_service["services"]["sesv2"] = regions_by_service["services"]["ses"] + # cognito --> cognito-idp + regions_by_service["services"]["cognito"] = regions_by_service["services"][ + "cognito-idp" + ] + # opensearch --> es + regions_by_service["services"]["opensearch"] = regions_by_service["services"]["es"] + # elbv2 --> elb + regions_by_service["services"]["elbv2"] = regions_by_service["services"]["elb"] + # wafv2 --> waf + regions_by_service["services"]["wafv2"] = regions_by_service["services"]["waf"] + # wellarchitected --> wellarchitectedtool + regions_by_service["services"]["wellarchitected"] = regions_by_service["services"][ + "wellarchitectedtool" + ] + # sesv2 --> ses + regions_by_service["services"]["sesv2"] = regions_by_service["services"]["ses"] -# Write to file -parsed_matrix_regions_aws = f"{os.path.dirname(os.path.realpath(__name__))}/prowler/providers/aws/aws_regions_by_service.json" -logging.info(f"Writing {parsed_matrix_regions_aws}") -with open(parsed_matrix_regions_aws, "w") as outfile: - json.dump(regions_by_service, outfile, indent=2, sort_keys=True) - outfile.write("\n") + +def get_endpoint_prefix_to_services() -> dict: + """Map every botocore endpoint prefix to the set of boto3 service (client) + names using it. + + botocore's endpoints.json keys services by endpoint prefix, while the matrix + keys them by the boto3/SSM service name. The mapping is derived from the SDK + itself instead of being hand-written, so it stays correct as the SDK evolves + (monitoring -> cloudwatch, elasticloadbalancing -> elb and elbv2, states -> + stepfunctions, api.ecr -> ecr, ...). + + Returns: + dict: A dictionary mapping each endpoint prefix to a set of service names. + """ + session = BotocoreSession() + endpoint_prefix_to_services = {} + for service_name in session.get_available_services(): + endpoint_prefix = session.get_service_model(service_name).endpoint_prefix + endpoint_prefix_to_services.setdefault(endpoint_prefix, set()).add(service_name) + return endpoint_prefix_to_services + + +def resolve_matrix_services( + endpoint_prefix: str, endpoint_prefix_to_services: dict, services: dict +) -> set: + """Resolve a botocore endpoint prefix to the matrix service names it stands + for. + + Args: + - endpoint_prefix: The botocore endpoint prefix. + - endpoint_prefix_to_services: The map returned by get_endpoint_prefix_to_services. + - services: The services of the AWS regions matrix. + + Returns: + set: The matrix service names, empty when the prefix does not resolve. + """ + renamed_service = ISO_ENDPOINT_PREFIX_RENAMES.get(endpoint_prefix) + if renamed_service: + return {renamed_service} & set(services) + + service_names = endpoint_prefix_to_services.get(endpoint_prefix, set()) & set( + services + ) + if not service_names and endpoint_prefix in services: + service_names = {endpoint_prefix} + return service_names + + +def get_partition_global_service_regions( + service_names: set, service_data: dict, partition_regions: list +) -> list: + """Get the regions of a service whose only endpoint in the partition is the + partition-wide pseudo endpoint (for example "aws-iso-global"), which is not + a region and must never be recorded as one. + + Returns: + list: Every region of the partition, or only the credentialScope region + for the services the matrix records as single-region ones. + """ + partition_endpoint = service_data.get("partitionEndpoint") + credential_scope_region = ( + service_data.get("endpoints", {}) + .get(partition_endpoint, {}) + .get("credentialScope", {}) + .get("region") + ) + if service_names & ISO_SINGLE_REGION_PARTITION_GLOBAL_SERVICES: + if credential_scope_region in partition_regions: + return [credential_scope_region] + return [] + return list(partition_regions) + + +def add_iso_partitions_regions(regions_by_service: dict) -> None: + """Fill the aws-iso, aws-iso-b, aws-iso-e and aws-iso-f regions of every + service from the endpoints.json bundled with botocore. + + It runs after the subservices and the services not present in the original + matrix have been added, so it sees the final set of services: the aliases + sharing a single dict and the hand-written bedrock-agent entry all get their + ISO partition keys. + + Raises: + ValueError: If an endpoint prefix present in an ISO partition does not + resolve to a matrix service and is not explicitly ignored. + """ + logging.info("Updating the ISO partitions regions from the botocore endpoints") + services = regions_by_service["services"] + endpoints_data = BotocoreSession().get_data("endpoints") + endpoint_prefix_to_services = get_endpoint_prefix_to_services() + + # Every service carries every partition key, so the matrix stays rectangular + # even for the services with no presence at all in the ISO partitions. + for service in services.values(): + for partition in ISO_PARTITIONS: + service["regions"].setdefault(partition, []) + + for partition_data in endpoints_data["partitions"]: + partition = partition_data["partition"] + if partition not in ISO_PARTITIONS: + continue + partition_regions = sorted(partition_data.get("regions", {})) + for endpoint_prefix, service_data in partition_data.get("services", {}).items(): + if endpoint_prefix in ISO_IGNORED_ENDPOINT_PREFIXES: + continue + service_names = resolve_matrix_services( + endpoint_prefix, endpoint_prefix_to_services, services + ) + if not service_names: + raise ValueError( + f"The botocore endpoint prefix '{endpoint_prefix}', present in the " + f"'{partition}' partition, does not resolve to any service of the " + "AWS regions matrix. Dropping it silently would leave the service " + "out of the scans, so either add the prefix to " + "ISO_ENDPOINT_PREFIX_RENAMES with the matrix service name it " + "corresponds to, or add it to ISO_IGNORED_ENDPOINT_PREFIXES if it " + "must not be mapped." + ) + # Keep only the endpoints that are real regions of the partition, + # which drops the fips-* and the partition-wide pseudo endpoints. + regions = sorted( + set(service_data.get("endpoints", {})) & set(partition_regions) + ) + if not regions: + regions = get_partition_global_service_regions( + service_names, service_data, partition_regions + ) + for service_name in service_names: + services[service_name]["regions"][partition] = list(regions) + + +def write_regions_by_service(regions_by_service: dict) -> None: + """Write the AWS regions matrix to the file read by the AWS provider.""" + repository_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + parsed_matrix_regions_aws = ( + f"{repository_root}/prowler/providers/aws/aws_regions_by_service.json" + ) + logging.info(f"Writing {parsed_matrix_regions_aws}") + with open(parsed_matrix_regions_aws, "w") as outfile: + json.dump(regions_by_service, outfile, indent=2, sort_keys=True) + outfile.write("\n") + + +def main() -> None: + regions_by_service = get_regions_by_service_from_ssm() + add_subservices_and_missing_services(regions_by_service) + add_iso_partitions_regions(regions_by_service) + write_regions_by_service(regions_by_service) + + +if __name__ == "__main__": + main() From b378f1579869ed3f20fddb1712aa81610ab2d9e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Fri, 11 Sep 2026 08:37:20 +0200 Subject: [PATCH 51/77] fix(aws): guard checks reading iam roles when unlisted (#12785) --- .../aws-checks-roles-unlisted.fixed.md | 1 + ...oject_uses_allowed_github_organizations.py | 2 +- ...rvice_trust_restricts_source_to_account.py | 2 +- ...e_profile_restricts_session_permissions.py | 4 +- ..._uses_allowed_github_organizations_test.py | 55 ++++++++++++++++++- ..._trust_restricts_source_to_account_test.py | 4 ++ ...file_restricts_session_permissions_test.py | 13 +++++ 7 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 prowler/changelog.d/aws-checks-roles-unlisted.fixed.md diff --git a/prowler/changelog.d/aws-checks-roles-unlisted.fixed.md b/prowler/changelog.d/aws-checks-roles-unlisted.fixed.md new file mode 100644 index 0000000000..dc24ad1b49 --- /dev/null +++ b/prowler/changelog.d/aws-checks-roles-unlisted.fixed.md @@ -0,0 +1 @@ +`rolesanywhere_profile_restricts_session_permissions`, `iam_role_service_trust_restricts_source_to_account` and `codebuild_project_uses_allowed_github_organizations` crashing with `TypeError` when `iam:ListRoles` is denied diff --git a/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py index 750a5a6fdd..11bb9a8b00 100644 --- a/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py +++ b/prowler/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations.py @@ -23,7 +23,7 @@ class codebuild_project_uses_allowed_github_organizations(Check): project_role = next( ( role - for role in iam_client.roles + for role in iam_client.roles or [] if role.arn == project.service_role_arn ), None, diff --git a/prowler/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account.py b/prowler/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account.py index 795f39a458..07aa4ac073 100644 --- a/prowler/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account.py +++ b/prowler/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account.py @@ -377,7 +377,7 @@ class iam_role_service_trust_restricts_source_to_account(Check): status. The sibling token-wildcard check carries the same note, for the same reason. """ findings = [] - for role in iam_client.roles: + for role in iam_client.roles or []: # Service-linked roles are excluded: their trust relationship is managed by # the service and cannot be edited, so a finding would not be actionable. if "aws-service-role" in role.arn: diff --git a/prowler/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions.py b/prowler/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions.py index 5138b74ff3..2960518a67 100644 --- a/prowler/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions.py +++ b/prowler/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions.py @@ -205,7 +205,9 @@ class rolesanywhere_profile_restricts_session_permissions(Check): not administrative, and disabled profiles. """ findings = [] - roles_by_arn = {role.arn: role for role in iam_client.roles} + # iam:ListRoles denied leaves roles as None: every referenced role is + # then unknown and the profile falls through to MANUAL. + roles_by_arn = {role.arn: role for role in (iam_client.roles or [])} for profile in rolesanywhere_client.profiles.values(): report = Check_Report_AWS(metadata=self.metadata(), resource=profile) role_statuses = { diff --git a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py index bdabea03fa..0ac90d50d2 100644 --- a/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py +++ b/tests/providers/aws/services/codebuild/codebuild_project_uses_allowed_github_organizations/codebuild_project_uses_allowed_github_organizations_test.py @@ -1,4 +1,4 @@ -from unittest.mock import patch +from unittest.mock import MagicMock, patch from boto3 import client from moto import mock_aws @@ -182,6 +182,59 @@ class Test_codebuild_project_uses_allowed_github_organizations: ) assert result[0].region == AWS_REGION_EU_WEST_1 + @mock_aws + def test_project_github_with_unlisted_roles(self): + # iam:ListRoles denied leaves iam_client.roles as None. + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + codebuild_client = client("codebuild", region_name=AWS_REGION_EU_WEST_1) + codebuild_client.create_project( + name="test-project-github-unlisted-roles", + source={ + "type": "GITHUB", + "location": "https://github.com/allowed-org/repo", + }, + artifacts={"type": "NO_ARTIFACTS"}, + environment={ + "type": "LINUX_CONTAINER", + "image": "aws/codebuild/standard:4.0", + "computeType": "BUILD_GENERAL1_SMALL", + "environmentVariables": [], + }, + serviceRole=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/codebuild-test-role", + ) + + from prowler.providers.aws.services.codebuild.codebuild_service import Codebuild + + iam_client = MagicMock() + iam_client.roles = None + + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client", + new=Codebuild(aws_provider), + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.iam_client", + new=iam_client, + ), + patch( + "prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations.codebuild_client.audit_config", + {"codebuild_github_allowed_organizations": ["allowed-org"]}, + ), + ): + from prowler.providers.aws.services.codebuild.codebuild_project_uses_allowed_github_organizations.codebuild_project_uses_allowed_github_organizations import ( + codebuild_project_uses_allowed_github_organizations, + ) + + assert ( + len(codebuild_project_uses_allowed_github_organizations().execute()) + == 0 + ) + @mock_aws def test_project_github_no_codebuild_trusted_principal(self): aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) diff --git a/tests/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account_test.py b/tests/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account_test.py index e01bdb36ba..66e96c571d 100644 --- a/tests/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account_test.py +++ b/tests/providers/aws/services/iam/iam_role_service_trust_restricts_source_to_account/iam_role_service_trust_restricts_source_to_account_test.py @@ -93,6 +93,10 @@ class Test_iam_role_service_trust_restricts_source_to_account: """An account with no roles produces no reports at all.""" assert len(_run([])) == 0 + def test_unlisted_roles_produce_no_reports(self): + # iam:ListRoles denied leaves iam_client.roles as None. + assert len(_run(None)) == 0 + def test_service_linked_role_skipped(self): """A service-linked role is excluded even when its trust policy would FAIL. diff --git a/tests/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions_test.py b/tests/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions_test.py index 09cdb3ae8d..230523239d 100644 --- a/tests/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions_test.py +++ b/tests/providers/aws/services/rolesanywhere/rolesanywhere_profile_restricts_session_permissions/rolesanywhere_profile_restricts_session_permissions_test.py @@ -472,6 +472,19 @@ class Test_rolesanywhere_profile_restricts_session_permissions: assert result[0].status == "MANUAL" assert "could not be evaluated" in result[0].status_extended + def test_unscoped_profile_with_unlisted_roles_is_manual(self): + # iam:ListRoles denied leaves iam_client.roles as None. + patches = _patched( + _build_client({PROFILE_ARN: _profile(role_arns=[ADMIN_ROLE_ARN])}) + ) + patches[-1].new.roles = None + with _enter(patches): + result = _run() + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ADMIN_ROLE_ARN in result[0].status_extended + assert "could not be evaluated" in result[0].status_extended + def test_unscoped_profile_without_roles_passes(self): with _enter(_patched(_build_client({PROFILE_ARN: _profile(role_arns=[])}))): result = _run() From 4727da7ca71a87be629a888184705eb3f2e4324e Mon Sep 17 00:00:00 2001 From: Prowler Bot Date: Fri, 11 Sep 2026 10:21:17 +0200 Subject: [PATCH 52/77] chore(changelog): v5.42.0 (#12794) Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com> --- api/CHANGELOG.md | 8 ++++++ ...ompliance-overviews-ingest-perf.changed.md | 1 - mcp_server/CHANGELOG.md | 8 ++++++ .../mcp-image-libuuid-cves.security.md | 1 - prowler/CHANGELOG.md | 27 +++++++++++++++++++ ...s-boto3-connect-timeout-default.changed.md | 1 - .../changelog.d/aws-boto3-timeouts.added.md | 1 - .../aws-checks-roles-unlisted.fixed.md | 1 - .../changelog.d/aws-iso-partitions.added.md | 1 - .../changelog.d/aws-iso-partitions.fixed.md | 1 - ...-region-honours-configured-region.fixed.md | 1 - .../aws-regional-clients-empty-dict.fixed.md | 1 - .../aws-retries-max-attempts-zero.fixed.md | 1 - ...service-regions-unknown-partition.fixed.md | 1 - .../compliance-catalog-integrity.fixed.md | 1 - ...nection-test-parallel-issue-types.fixed.md | 1 - ...ue-types-permission-gap-log-level.fixed.md | 1 - ...threatscore-azure-gcp-data-errors.fixed.md | 1 - .../trivy-cache-dir-configurable.fixed.md | 1 - ui/CHANGELOG.md | 20 ++++++++++++++ ...pendabot-audit-vulnerabilities.security.md | 1 - ...tegration-connection-poll-timeout.fixed.md | 1 - .../next-image-optimization-rce.security.md | 1 - .../posthog-toolbar-localhost.added.md | 1 - ui/changelog.d/scans-filter-actions.fixed.md | 1 - .../sharp-libheif-vulnerabilities.security.md | 1 - .../view-first-scan-tour-selector.fixed.md | 1 - 27 files changed, 63 insertions(+), 23 deletions(-) delete mode 100644 api/changelog.d/compliance-overviews-ingest-perf.changed.md delete mode 100644 mcp_server/changelog.d/mcp-image-libuuid-cves.security.md delete mode 100644 prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md delete mode 100644 prowler/changelog.d/aws-boto3-timeouts.added.md delete mode 100644 prowler/changelog.d/aws-checks-roles-unlisted.fixed.md delete mode 100644 prowler/changelog.d/aws-iso-partitions.added.md delete mode 100644 prowler/changelog.d/aws-iso-partitions.fixed.md delete mode 100644 prowler/changelog.d/aws-partition-bootstrap-region-honours-configured-region.fixed.md delete mode 100644 prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md delete mode 100644 prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md delete mode 100644 prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md delete mode 100644 prowler/changelog.d/compliance-catalog-integrity.fixed.md delete mode 100644 prowler/changelog.d/jira-connection-test-parallel-issue-types.fixed.md delete mode 100644 prowler/changelog.d/jira-issue-types-permission-gap-log-level.fixed.md delete mode 100644 prowler/changelog.d/threatscore-azure-gcp-data-errors.fixed.md delete mode 100644 prowler/changelog.d/trivy-cache-dir-configurable.fixed.md delete mode 100644 ui/changelog.d/dependabot-audit-vulnerabilities.security.md delete mode 100644 ui/changelog.d/integration-connection-poll-timeout.fixed.md delete mode 100644 ui/changelog.d/next-image-optimization-rce.security.md delete mode 100644 ui/changelog.d/posthog-toolbar-localhost.added.md delete mode 100644 ui/changelog.d/scans-filter-actions.fixed.md delete mode 100644 ui/changelog.d/sharp-libheif-vulnerabilities.security.md delete mode 100644 ui/changelog.d/view-first-scan-tour-selector.fixed.md diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 0ab4c9bfe1..318cd30d4f 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to the **Prowler API** are documented in this file. +## [1.43.0] (Prowler v5.42.0) + +### 🔄 Changed + +- Speed up compliance overview ingestion by reading ThreatScore mappings from the compliance template instead of each finding, generating time-ordered `uuid7` row ids and grouping inserted rows by framework and requirement [(#12738)](https://github.com/prowler-cloud/prowler/pull/12738) + +--- + ## [1.42.0] (Prowler v5.41.0) ### 🚀 Added diff --git a/api/changelog.d/compliance-overviews-ingest-perf.changed.md b/api/changelog.d/compliance-overviews-ingest-perf.changed.md deleted file mode 100644 index 6e833d184e..0000000000 --- a/api/changelog.d/compliance-overviews-ingest-perf.changed.md +++ /dev/null @@ -1 +0,0 @@ -Speed up compliance overview ingestion by reading ThreatScore mappings from the compliance template instead of each finding, generating time-ordered `uuid7` row ids and grouping inserted rows by framework and requirement diff --git a/mcp_server/CHANGELOG.md b/mcp_server/CHANGELOG.md index 4c6c858d28..80bdabd28a 100644 --- a/mcp_server/CHANGELOG.md +++ b/mcp_server/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to the **Prowler MCP Server** are documented in this file. +## [0.12.1] (Prowler v5.42.0) + +### 🔐 Security + +- `libuuid` upgraded to 2.41.6-r1 in the container image, patching CVE-2026-53612, CVE-2026-53613, CVE-2026-53614, CVE-2026-76642, CVE-2026-78408 and CVE-2026-78410 [(#12780)](https://github.com/prowler-cloud/prowler/pull/12780) + +--- + ## [0.12.0] (Prowler v5.41.0) ### 🚀 Added diff --git a/mcp_server/changelog.d/mcp-image-libuuid-cves.security.md b/mcp_server/changelog.d/mcp-image-libuuid-cves.security.md deleted file mode 100644 index 602458c777..0000000000 --- a/mcp_server/changelog.d/mcp-image-libuuid-cves.security.md +++ /dev/null @@ -1 +0,0 @@ -`libuuid` upgraded to 2.41.6-r1 in the container image, patching CVE-2026-53612, CVE-2026-53613, CVE-2026-53614, CVE-2026-76642, CVE-2026-78408 and CVE-2026-78410 diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 4161d195b8..7232bd41a0 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -4,6 +4,33 @@ All notable changes to the **Prowler SDK** are documented in this file. +## [5.42.0] (Prowler v5.42.0) + +### 🚀 Added + +- AWS ISO partitions (`aws-iso`, `aws-iso-b`, `aws-iso-e` and `aws-iso-f`) to the AWS service region matrix, generated from the endpoints data bundled with botocore [(#12759)](https://github.com/prowler-cloud/prowler/pull/12759) +- `--aws-connect-timeout` and `--aws-read-timeout` CLI flags, plus `PROWLER_AWS_BOTO3_CONNECT_TIMEOUT` and `PROWLER_AWS_BOTO3_READ_TIMEOUT` environment variables, to bound how long each AWS API call waits for an endpoint [(#12774)](https://github.com/prowler-cloud/prowler/pull/12774) + +### 🔄 Changed + +- AWS provider default Boto3 connect timeout lowered from 60 to 10 seconds, so scans in restricted-egress networks (VPC endpoints for a subset of services, GovCloud, private deployments) no longer spend 4 minutes per region on every service whose endpoint is unreachable [(#12774)](https://github.com/prowler-cloud/prowler/pull/12774) + +### 🐞 Fixed + +- Duplicate requirement ids, checks listed twice in a requirement and references to non-existent checks across compliance frameworks, now guarded by a catalog integrity test [(#12717)](https://github.com/prowler-cloud/prowler/pull/12717) +- Duplicate requirement `3.2.1` in ProwlerThreatScore for Azure (SQL auditing retention is now `3.2.4`) and doubled check id in requirement `1.2.1` of ProwlerThreatScore for GCP [(#12717)](https://github.com/prowler-cloud/prowler/pull/12717) +- Jira connection checks no longer log an error when a single project has no issue types visible to the integration user (typically a missing "create issue" permission on that project), a case the caller already treats as non-fatal [(#12742)](https://github.com/prowler-cloud/prowler/pull/12742) +- `Jira.test_connection()` now fetches each project's issue types concurrently instead of one request at a time, so accounts with many Jira projects no longer take tens of seconds (unbounded, scaling with the project count) to verify the connection [(#12742)](https://github.com/prowler-cloud/prowler/pull/12742) +- `AwsProvider.get_available_aws_service_regions()` now returns an empty set for an unknown service or partition instead of raising `KeyError`, so a service unavailable in the audited partition is skipped [(#12759)](https://github.com/prowler-cloud/prowler/pull/12759) +- `AwsProvider.generate_regional_clients()` now returns an empty dict instead of `None` when the regional clients cannot be built, a failure that surfaced later as `AttributeError: 'NoneType' object has no attribute 'values'` [(#12759)](https://github.com/prowler-cloud/prowler/pull/12759) +- `AwsProvider.get_global_region()` now returns a real region for each ISO partition instead of the `aws-iso-global` pseudo endpoint, which collapsed the four partitions into one answer [(#12759)](https://github.com/prowler-cloud/prowler/pull/12759) +- Bootstrap STS calls now use the session region when `PROWLER_AWS_PARTITION` is set and the region belongs to that partition, instead of always going to the partition's global STS region, which a deployment reached only through its own region's VPC endpoints cannot route to [(#12764)](https://github.com/prowler-cloud/prowler/pull/12764) +- The Image provider now uses the directory named by `TRIVY_CACHE_DIR` when one is set, instead of a fresh temporary directory it deletes afterwards, so a deployment can supply a vulnerability database it already holds and one with network access stops re-downloading the database for every image it scans [(#12773)](https://github.com/prowler-cloud/prowler/pull/12773) +- `--aws-retries-max-attempts 0` now disables Boto3 retries instead of being silently ignored in favour of the default of 3 [(#12774)](https://github.com/prowler-cloud/prowler/pull/12774) +- `rolesanywhere_profile_restricts_session_permissions`, `iam_role_service_trust_restricts_source_to_account` and `codebuild_project_uses_allowed_github_organizations` crashing with `TypeError` when `iam:ListRoles` is denied [(#12785)](https://github.com/prowler-cloud/prowler/pull/12785) + +--- + ## [5.41.0] (Prowler v5.41.0) ### 🚀 Added diff --git a/prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md b/prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md deleted file mode 100644 index a204443b2a..0000000000 --- a/prowler/changelog.d/aws-boto3-connect-timeout-default.changed.md +++ /dev/null @@ -1 +0,0 @@ -AWS provider default Boto3 connect timeout lowered from 60 to 10 seconds, so scans in restricted-egress networks (VPC endpoints for a subset of services, GovCloud, private deployments) no longer spend 4 minutes per region on every service whose endpoint is unreachable diff --git a/prowler/changelog.d/aws-boto3-timeouts.added.md b/prowler/changelog.d/aws-boto3-timeouts.added.md deleted file mode 100644 index df5d6e4f2b..0000000000 --- a/prowler/changelog.d/aws-boto3-timeouts.added.md +++ /dev/null @@ -1 +0,0 @@ -`--aws-connect-timeout` and `--aws-read-timeout` CLI flags, plus `PROWLER_AWS_BOTO3_CONNECT_TIMEOUT` and `PROWLER_AWS_BOTO3_READ_TIMEOUT` environment variables, to bound how long each AWS API call waits for an endpoint diff --git a/prowler/changelog.d/aws-checks-roles-unlisted.fixed.md b/prowler/changelog.d/aws-checks-roles-unlisted.fixed.md deleted file mode 100644 index dc24ad1b49..0000000000 --- a/prowler/changelog.d/aws-checks-roles-unlisted.fixed.md +++ /dev/null @@ -1 +0,0 @@ -`rolesanywhere_profile_restricts_session_permissions`, `iam_role_service_trust_restricts_source_to_account` and `codebuild_project_uses_allowed_github_organizations` crashing with `TypeError` when `iam:ListRoles` is denied diff --git a/prowler/changelog.d/aws-iso-partitions.added.md b/prowler/changelog.d/aws-iso-partitions.added.md deleted file mode 100644 index 41282ea353..0000000000 --- a/prowler/changelog.d/aws-iso-partitions.added.md +++ /dev/null @@ -1 +0,0 @@ -AWS ISO partitions (`aws-iso`, `aws-iso-b`, `aws-iso-e` and `aws-iso-f`) to the AWS service region matrix, generated from the endpoints data bundled with botocore diff --git a/prowler/changelog.d/aws-iso-partitions.fixed.md b/prowler/changelog.d/aws-iso-partitions.fixed.md deleted file mode 100644 index c3424d51ba..0000000000 --- a/prowler/changelog.d/aws-iso-partitions.fixed.md +++ /dev/null @@ -1 +0,0 @@ -`AwsProvider.get_global_region()` now returns a real region for each ISO partition instead of the `aws-iso-global` pseudo endpoint, which collapsed the four partitions into one answer diff --git a/prowler/changelog.d/aws-partition-bootstrap-region-honours-configured-region.fixed.md b/prowler/changelog.d/aws-partition-bootstrap-region-honours-configured-region.fixed.md deleted file mode 100644 index 93a6c8d7b1..0000000000 --- a/prowler/changelog.d/aws-partition-bootstrap-region-honours-configured-region.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Bootstrap STS calls now use the session region when `PROWLER_AWS_PARTITION` is set and the region belongs to that partition, instead of always going to the partition's global STS region, which a deployment reached only through its own region's VPC endpoints cannot route to diff --git a/prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md b/prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md deleted file mode 100644 index bd5f7798ac..0000000000 --- a/prowler/changelog.d/aws-regional-clients-empty-dict.fixed.md +++ /dev/null @@ -1 +0,0 @@ -`AwsProvider.generate_regional_clients()` now returns an empty dict instead of `None` when the regional clients cannot be built, a failure that surfaced later as `AttributeError: 'NoneType' object has no attribute 'values'` diff --git a/prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md b/prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md deleted file mode 100644 index 8eb2ad9e07..0000000000 --- a/prowler/changelog.d/aws-retries-max-attempts-zero.fixed.md +++ /dev/null @@ -1 +0,0 @@ -`--aws-retries-max-attempts 0` now disables Boto3 retries instead of being silently ignored in favour of the default of 3 diff --git a/prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md b/prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md deleted file mode 100644 index 881ce2c94b..0000000000 --- a/prowler/changelog.d/aws-service-regions-unknown-partition.fixed.md +++ /dev/null @@ -1 +0,0 @@ -`AwsProvider.get_available_aws_service_regions()` now returns an empty set for an unknown service or partition instead of raising `KeyError`, so a service unavailable in the audited partition is skipped diff --git a/prowler/changelog.d/compliance-catalog-integrity.fixed.md b/prowler/changelog.d/compliance-catalog-integrity.fixed.md deleted file mode 100644 index 1bfcf0462c..0000000000 --- a/prowler/changelog.d/compliance-catalog-integrity.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Duplicate requirement ids, checks listed twice in a requirement and references to non-existent checks across compliance frameworks, now guarded by a catalog integrity test diff --git a/prowler/changelog.d/jira-connection-test-parallel-issue-types.fixed.md b/prowler/changelog.d/jira-connection-test-parallel-issue-types.fixed.md deleted file mode 100644 index 85d3bad72a..0000000000 --- a/prowler/changelog.d/jira-connection-test-parallel-issue-types.fixed.md +++ /dev/null @@ -1 +0,0 @@ -`Jira.test_connection()` now fetches each project's issue types concurrently instead of one request at a time, so accounts with many Jira projects no longer take tens of seconds (unbounded, scaling with the project count) to verify the connection diff --git a/prowler/changelog.d/jira-issue-types-permission-gap-log-level.fixed.md b/prowler/changelog.d/jira-issue-types-permission-gap-log-level.fixed.md deleted file mode 100644 index 0d0a1f5477..0000000000 --- a/prowler/changelog.d/jira-issue-types-permission-gap-log-level.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Jira connection checks no longer log an error when a single project has no issue types visible to the integration user (typically a missing "create issue" permission on that project), a case the caller already treats as non-fatal diff --git a/prowler/changelog.d/threatscore-azure-gcp-data-errors.fixed.md b/prowler/changelog.d/threatscore-azure-gcp-data-errors.fixed.md deleted file mode 100644 index 0fb7547adb..0000000000 --- a/prowler/changelog.d/threatscore-azure-gcp-data-errors.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Duplicate requirement `3.2.1` in ProwlerThreatScore for Azure (SQL auditing retention is now `3.2.4`) and doubled check id in requirement `1.2.1` of ProwlerThreatScore for GCP diff --git a/prowler/changelog.d/trivy-cache-dir-configurable.fixed.md b/prowler/changelog.d/trivy-cache-dir-configurable.fixed.md deleted file mode 100644 index fd2f0ca117..0000000000 --- a/prowler/changelog.d/trivy-cache-dir-configurable.fixed.md +++ /dev/null @@ -1 +0,0 @@ -The Image provider now uses the directory named by `TRIVY_CACHE_DIR` when one is set, instead of a fresh temporary directory it deletes afterwards, so a deployment can supply a vulnerability database it already holds and one with network access stops re-downloading the database for every image it scans diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index eeadba64b8..8687ddde54 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -4,6 +4,26 @@ All notable changes to the **Prowler UI** are documented in this file. +## [1.42.0] (Prowler v5.42.0) + +### 🚀 Added + +- PostHog Toolbar support in development with separate ingestion and app hosts [(#12582)](https://github.com/prowler-cloud/prowler/pull/12582) + +### 🐞 Fixed + +- Scan Jobs onboarding tour no longer targets an unmounted In Progress row from other tabs [(#12705)](https://github.com/prowler-cloud/prowler/pull/12705) +- Integration connection test polling now waits up to ~3 minutes instead of ~57 seconds before giving up, so it no longer reports a false failure on slower checks (e.g. Jira accounts with many projects) that were still going to succeed [(#12742)](https://github.com/prowler-cloud/prowler/pull/12742) +- Scans page filter widths and action button styling, with Launch Scan and Import Findings grouped beside the tabs and sized consistently with Configure Mutelist [(#12781)](https://github.com/prowler-cloud/prowler/pull/12781) + +### 🔐 Security + +- `nanoid` to 5.1.16, `js-yaml` to 4.3.1 and `postcss` to 8.5.23, plus transitive `hono`, `@hono/node-server`, `browserslist`, `qs`, `dompurify`, `brace-expansion`, `fast-uri`, `ip-address`, `mermaid`, `body-parser` and `@humanfs/node` to patched versions, resolving 40 npm audit advisories (21 high, 15 moderate, 4 low) [(#12758)](https://github.com/prowler-cloud/prowler/pull/12758) +- `next` to 16.3.3, patching an unauthenticated remote code execution in the Image Optimization API when AVIF files are used (GHSA-2xp9-vwfh-vxw4) [(#12778)](https://github.com/prowler-cloud/prowler/pull/12778) +- `sharp` to 0.35.4, patching two libheif vulnerabilities reachable through image decoding (GHSA-rgj7-g3m4-5g8c) [(#12778)](https://github.com/prowler-cloud/prowler/pull/12778) + +--- + ## [1.41.0] (Prowler v5.41.0) ### 🚀 Added diff --git a/ui/changelog.d/dependabot-audit-vulnerabilities.security.md b/ui/changelog.d/dependabot-audit-vulnerabilities.security.md deleted file mode 100644 index 9d030097f0..0000000000 --- a/ui/changelog.d/dependabot-audit-vulnerabilities.security.md +++ /dev/null @@ -1 +0,0 @@ -`nanoid` to 5.1.16, `js-yaml` to 4.3.1 and `postcss` to 8.5.23, plus transitive `hono`, `@hono/node-server`, `browserslist`, `qs`, `dompurify`, `brace-expansion`, `fast-uri`, `ip-address`, `mermaid`, `body-parser` and `@humanfs/node` to patched versions, resolving 40 npm audit advisories (21 high, 15 moderate, 4 low) diff --git a/ui/changelog.d/integration-connection-poll-timeout.fixed.md b/ui/changelog.d/integration-connection-poll-timeout.fixed.md deleted file mode 100644 index 629eef9a45..0000000000 --- a/ui/changelog.d/integration-connection-poll-timeout.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Integration connection test polling now waits up to ~3 minutes instead of ~57 seconds before giving up, so it no longer reports a false failure on slower checks (e.g. Jira accounts with many projects) that were still going to succeed diff --git a/ui/changelog.d/next-image-optimization-rce.security.md b/ui/changelog.d/next-image-optimization-rce.security.md deleted file mode 100644 index 5000fa95f8..0000000000 --- a/ui/changelog.d/next-image-optimization-rce.security.md +++ /dev/null @@ -1 +0,0 @@ -`next` to 16.3.3, patching an unauthenticated remote code execution in the Image Optimization API when AVIF files are used (GHSA-2xp9-vwfh-vxw4) diff --git a/ui/changelog.d/posthog-toolbar-localhost.added.md b/ui/changelog.d/posthog-toolbar-localhost.added.md deleted file mode 100644 index a2aa815a1c..0000000000 --- a/ui/changelog.d/posthog-toolbar-localhost.added.md +++ /dev/null @@ -1 +0,0 @@ -PostHog Toolbar support in development with separate ingestion and app hosts diff --git a/ui/changelog.d/scans-filter-actions.fixed.md b/ui/changelog.d/scans-filter-actions.fixed.md deleted file mode 100644 index 3220d59a8e..0000000000 --- a/ui/changelog.d/scans-filter-actions.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Scans page filter widths and action button styling, with Launch Scan and Import Findings grouped beside the tabs and sized consistently with Configure Mutelist diff --git a/ui/changelog.d/sharp-libheif-vulnerabilities.security.md b/ui/changelog.d/sharp-libheif-vulnerabilities.security.md deleted file mode 100644 index 75296b55dc..0000000000 --- a/ui/changelog.d/sharp-libheif-vulnerabilities.security.md +++ /dev/null @@ -1 +0,0 @@ -`sharp` to 0.35.4, patching two libheif vulnerabilities reachable through image decoding (GHSA-rgj7-g3m4-5g8c) diff --git a/ui/changelog.d/view-first-scan-tour-selector.fixed.md b/ui/changelog.d/view-first-scan-tour-selector.fixed.md deleted file mode 100644 index 13f56ac446..0000000000 --- a/ui/changelog.d/view-first-scan-tour-selector.fixed.md +++ /dev/null @@ -1 +0,0 @@ -Scan Jobs onboarding tour no longer targets an unmounted In Progress row from other tabs From c08cb65d8480fae1f37216824d84a1cfc3503d2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Fri, 11 Sep 2026 12:11:44 +0200 Subject: [PATCH 53/77] chore(changelog): v5.42.0 highlights (#12795) Co-authored-by: Pepe Fagoaga --- docs/changelog.mdx | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/docs/changelog.mdx b/docs/changelog.mdx index 40df5cb9df..db0bb4409c 100644 --- a/docs/changelog.mdx +++ b/docs/changelog.mdx @@ -4,6 +4,62 @@ description: "New features and improvements in each Prowler release" rss: true --- + + ### ☁️ AWS — ISO Partitions + + Prowler now resolves regions and services for the AWS ISO partitions (`aws-iso`, `aws-iso-b`, `aws-iso-e` and `aws-iso-f`) the same way it does for the commercial, China, European Sovereign Cloud and GovCloud partitions. The region matrix is filled from the endpoint metadata bundled with botocore, which needs no credentials or network access, so it covers partitions that are air-gapped from the internet. Scanning them no longer requires a hand-edited `aws_regions_by_service.json`: ISO regions such as `us-isob-east-1` are accepted by `--region` and `--excluded-region`. + + Deployments that declare `PROWLER_AWS_PARTITION` also keep their bootstrap STS calls in the configured region when it belongs to that partition. An install in `us-gov-west-1` that reaches AWS only through its own VPC endpoints is no longer sent to `us-gov-east-1`, where the connection check and the scan used to time out. + + Read more in the [AWS Regions and Partitions documentation](https://docs.prowler.com/user-guide/providers/aws/regions-and-partitions). + + ### ⏱️ AWS — Configurable Timeouts for Restricted Networks + + Scans from networks with restricted egress (VPC endpoints for only some services, GovCloud or private deployments) could take hours: Boto3 waits 60 seconds to connect by default and retries connection errors, so every service without a reachable endpoint cost up to four 60-second attempts in every region. Prowler now lowers the default connect timeout to 10 seconds, keeps the read timeout at 60 seconds, and exposes both through `--aws-connect-timeout` and `--aws-read-timeout`, or through the `PROWLER_AWS_BOTO3_CONNECT_TIMEOUT` and `PROWLER_AWS_BOTO3_READ_TIMEOUT` environment variables for deployments without a CLI. `--aws-retries-max-attempts 0` now disables retries instead of silently falling back to three, leaving a single attempt per call. + + Read more in the [Boto3 configuration documentation](https://docs.prowler.com/user-guide/providers/aws/boto3-configuration). + + ### 🐳 Image Provider — Reusable Vulnerability Database + + The Image provider now honors `TRIVY_CACHE_DIR`. When the variable names a directory, Trivy keeps its vulnerability database there and Prowler leaves the directory in place after the scan, so the database is downloaded once instead of on every scan. Hosts without internet access can now scan images by pointing `TRIVY_CACHE_DIR` at a pre-populated database and setting `TRIVY_SKIP_DB_UPDATE=true`. Without the variable, the temporary cache is created and removed as before. + + Read more in the [Image provider documentation](https://docs.prowler.com/user-guide/providers/image/getting-started-image#vulnerability-database-cache). + + ### 🎫 Jira Integration — Faster Connection Test + + Testing a Jira integration no longer reports a false failure on accounts with many projects. The connection test fetched the issue types of every project one request at a time, which could outlast the wait in the UI even when the check was about to succeed. Issue types are now fetched concurrently, a project whose issue types the integration user cannot see is no longer logged as an error, and the Integrations page keeps following the connection test instead of giving up after about a minute. + + Read more in the [Jira integration documentation](https://docs.prowler.com/user-guide/tutorials/prowler-app-jira-integration). + + ### 📚 Compliance — Catalog Integrity Fixes + + A new integrity test runs over every compliance framework, asserting unique requirement IDs, no check listed twice within a requirement, and that every referenced check exists for its provider. The fixes it drove span 42 frameworks across AWS, Azure, GCP, GitHub, Kubernetes and Microsoft 365: + + - **Duplicate requirement IDs:** identical copies are removed, and distinct requirements that shared an ID get their own, such as `1.10` in CIS AWS 5.0 and `rc_rp_1` for RC.RP-1 in NIST CSF 1.1. In Prowler ThreatScore for Azure, SQL auditing retention moves from `3.2.1` to `3.2.4`, and requirement `1.2.1` of Prowler ThreatScore for GCP now points to `iam_sa_no_user_managed_keys`. + - **Stale check references:** checks that no longer exist are replaced with their current name when there is a direct equivalent, or removed so the requirement reports as manual. Most of these were in the FedRAMP 20x KSI frameworks. + + Renamed requirement IDs appear as new requirements for scans run after the upgrade. + + The compliance overview task that runs after every scan is also faster: ThreatScore mappings are read once from the compliance template instead of from every finding, and rows are inserted with time-ordered `uuid7` IDs grouped by framework and requirement. + + Read more in the [Compliance documentation](https://docs.prowler.com/user-guide/compliance/tutorials/compliance). + + ### 🔍 Checks + + `rolesanywhere_profile_restricts_session_permissions`, `iam_role_service_trust_restricts_source_to_account` and `codebuild_project_uses_allowed_github_organizations` no longer crash with `TypeError` when the scanning role is denied `iam:ListRoles`, which dropped every finding of those checks for the account. Without the role inventory, an enabled IAM Roles Anywhere profile without session scoping reports `MANUAL`, and CodeBuild projects whose service role cannot be resolved are skipped. + + Explore all AWS checks at [Prowler Hub](https://hub.prowler.com/check?provider=aws). + + ### 🔐 Security Updates + + - `next` upgraded to 16.3.3 in the UI, patching unauthenticated remote code execution through AVIF image optimization ([GHSA-2xp9-vwfh-vxw4](https://github.com/advisories/GHSA-2xp9-vwfh-vxw4)) and on Windows-hosted servers ([GHSA-p293-qw3h-jr36](https://github.com/advisories/GHSA-p293-qw3h-jr36)). + - `sharp` upgraded to 0.35.4 in the UI, patching libheif image-decoding vulnerabilities ([GHSA-rgj7-g3m4-5g8c](https://github.com/advisories/GHSA-rgj7-g3m4-5g8c)). + - `nanoid`, `js-yaml` and `postcss`, plus eleven transitive UI dependencies, upgraded to patched versions, resolving 40 npm audit advisories (21 high, 15 moderate, 4 low). + - `libuuid` upgraded to 2.41.6-r1 in the MCP Server image, patching CVE-2026-53612, CVE-2026-53613, CVE-2026-53614, CVE-2026-76642, CVE-2026-78408 and CVE-2026-78410. + + See the [full release notes on GitHub](https://github.com/prowler-cloud/prowler/releases/tag/5.42.0) for the complete list of changes. + + ### 📥 Scans — Import Findings from the Browser From 282fe5b46b96e5bcb7a22d0faca6519acffa3978 Mon Sep 17 00:00:00 2001 From: Prowler Bot Date: Fri, 11 Sep 2026 13:23:08 +0200 Subject: [PATCH 54/77] chore(release): Bump versions to v5.43.0 (#12797) Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com> --- .env | 2 +- api/pyproject.toml | 2 +- api/src/backend/api/specs/v1.yaml | 2 +- api/uv.lock | 2 +- docs/getting-started/installation/prowler-app.mdx | 4 ++-- prowler/config/config.py | 2 +- pyproject.toml | 2 +- uv.lock | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.env b/.env index 018b25a8a9..721d25f4bf 100644 --- a/.env +++ b/.env @@ -158,7 +158,7 @@ SENTRY_RELEASE=local # REO_DEV_CLIENT_ID= #### Prowler release version #### -NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v5.42.0 +NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v5.43.0 # Social login credentials SOCIAL_GOOGLE_OAUTH_CALLBACK_URL="${AUTH_URL}/api/auth/callback/google" diff --git a/api/pyproject.toml b/api/pyproject.toml index f9af7f04be..00b50e8300 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -71,7 +71,7 @@ name = "prowler-api" package-mode = false # Needed for the SDK compatibility requires-python = ">=3.11,<3.13" -version = "1.43.0" +version = "1.44.0" # Shared ruff baseline (kept in sync with mcp_server/pyproject.toml). # target-version tracks this project's lowest supported Python. diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index 4b5cebdb2e..ab57f94702 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -1,7 +1,7 @@ openapi: 3.0.3 info: title: Prowler API - version: 1.43.0 + version: 1.44.0 description: |- Prowler API specification. diff --git a/api/uv.lock b/api/uv.lock index bfaad1f98a..a835e2f223 100644 --- a/api/uv.lock +++ b/api/uv.lock @@ -4938,7 +4938,7 @@ dependencies = [ [[package]] name = "prowler-api" -version = "1.43.0" +version = "1.44.0" source = { virtual = "." } dependencies = [ { name = "cartography" }, diff --git a/docs/getting-started/installation/prowler-app.mdx b/docs/getting-started/installation/prowler-app.mdx index e9ec980e09..b27b7142d2 100644 --- a/docs/getting-started/installation/prowler-app.mdx +++ b/docs/getting-started/installation/prowler-app.mdx @@ -128,8 +128,8 @@ To update the environment file: Edit the `.env` file and change version values: ```env -PROWLER_UI_VERSION="5.41.0" -PROWLER_API_VERSION="5.41.0" +PROWLER_UI_VERSION="5.42.0" +PROWLER_API_VERSION="5.42.0" ``` diff --git a/prowler/config/config.py b/prowler/config/config.py index f1aa774ce2..21929b5099 100644 --- a/prowler/config/config.py +++ b/prowler/config/config.py @@ -52,7 +52,7 @@ class _MutableTimestamp: timestamp = _MutableTimestamp(datetime.today()) timestamp_utc = _MutableTimestamp(datetime.now(timezone.utc)) -prowler_version = "5.42.0" +prowler_version = "5.43.0" html_logo_url = "https://github.com/prowler-cloud/prowler/" square_logo_img = "https://raw.githubusercontent.com/prowler-cloud/prowler/dc7d2d5aeb92fdf12e8604f42ef6472cd3e8e889/docs/img/prowler-logo-black.png" aws_logo = "https://user-images.githubusercontent.com/38561120/235953920-3e3fba08-0795-41dc-b480-9bea57db9f2e.png" diff --git a/pyproject.toml b/pyproject.toml index cabf2740f7..8e49417f09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -143,7 +143,7 @@ maintainers = [{name = "Prowler Engineering", email = "engineering@prowler.com"} name = "prowler" readme = "README.md" requires-python = ">=3.10,<3.14" -version = "5.42.0" +version = "5.43.0" [project.scripts] prowler = "prowler.__main__:prowler" diff --git a/uv.lock b/uv.lock index fe04be07b8..ca1afd8346 100644 --- a/uv.lock +++ b/uv.lock @@ -3752,7 +3752,7 @@ wheels = [ [[package]] name = "prowler" -version = "5.42.0" +version = "5.43.0" source = { editable = "." } dependencies = [ { name = "alibabacloud-actiontrail20200706" }, From ba258a5346eddd1afd753deee6c2d884c13cf5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Mon, 14 Sep 2026 11:01:15 +0200 Subject: [PATCH 55/77] fix(container): patch high Debian CVEs in SDK and API (#12804) --- Dockerfile | 15 ++++++++++----- api/Dockerfile | 15 ++++++++++----- api/changelog.d/api-image-debian-cves.security.md | 1 + .../changelog.d/sdk-image-debian-cves.security.md | 1 + 4 files changed, 22 insertions(+), 10 deletions(-) create mode 100644 api/changelog.d/api-image-debian-cves.security.md create mode 100644 prowler/changelog.d/sdk-image-debian-cves.security.md diff --git a/Dockerfile b/Dockerfile index fdc85831de..559b39c9eb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,20 +22,25 @@ ARG POWERSHELL_SHA256_ARM64=2503b71da3e83635592b092df59a0aca4c3606b4d9b068217bb0 ARG ZIZMOR_SHA256_AMD64=a8000f3c683319a523d3b20df0e75457ba591f049cfcbfa98966631b56733c03 ARG ZIZMOR_SHA256_ARM64=d66e37ef8a375fb07939c630ebf9709a6e0f20242bdc3faf672a7ed97e0b768d -# High CVEs fixed in Debian trixie-security but not yet in the pinned base image: +# High CVEs fixed in Debian trixie but not yet in the pinned base image: # openssl/libssl3t64/openssl-provider-legacy 3.5.7-1~deb13u2 CVE-2026-14456, # -14457, -18798, -54874, -63072, -63073, -63074, -63075, -63076, -75803 -# (image ships 3.5.6-1~deb13u2) +# libsqlite3-0 3.46.1-7+deb13u2 CVE-2026-11822, -11824 +# gzip 1.13-1+deb13u1 CVE-2026-41992 +# perl-base 5.40.1-6+deb13u1 CVE-2026-42497, -48962, -57432 +# libssh2-1t64 1.11.1-1+deb13u2 CVE-2026-58050 +# libpcre2-8-0 10.46-1~deb13u2 CVE-2026-86145, -89161 # Taken as a targeted --only-upgrade rather than by moving the digest: the newest -# published python:3.12-slim-trixie carries the same vulnerable version. The three -# packages are all built from openssl and are flagged separately, so all are named. -# Drop them once the base image ships 3.5.7-1~deb13u2 or later. +# published python:3.12-slim-trixie carries the same vulnerable versions. The three +# openssl packages are flagged separately, so all are named. +# Drop each one once the base image ships its fixed version. # hadolint ignore=DL3008 RUN apt-get update && apt-get install -y --no-install-recommends \ wget libicu76 libunwind8 libssl3 libcurl4 ca-certificates apt-transport-https gnupg \ build-essential pkg-config libzstd-dev zlib1g-dev \ && apt-get install -y --no-install-recommends --only-upgrade \ util-linux libssl3t64 openssl openssl-provider-legacy \ + libsqlite3-0 gzip perl-base libssh2-1t64 libpcre2-8-0 \ && rm -rf /var/lib/apt/lists/* # Install PowerShell diff --git a/api/Dockerfile b/api/Dockerfile index 6866494bb4..ce5bccbb2c 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -21,14 +21,18 @@ ARG POWERSHELL_SHA256_ARM64=2503b71da3e83635592b092df59a0aca4c3606b4d9b068217bb0 ARG ZIZMOR_SHA256_AMD64=a8000f3c683319a523d3b20df0e75457ba591f049cfcbfa98966631b56733c03 ARG ZIZMOR_SHA256_ARM64=d66e37ef8a375fb07939c630ebf9709a6e0f20242bdc3faf672a7ed97e0b768d -# High CVEs fixed in Debian trixie-security but not yet in the pinned base image: +# High CVEs fixed in Debian trixie but not yet in the pinned base image: # openssl/libssl3t64/openssl-provider-legacy 3.5.7-1~deb13u2 CVE-2026-14456, # -14457, -18798, -54874, -63072, -63073, -63074, -63075, -63076, -75803 -# (image ships 3.5.6-1~deb13u2) +# libsqlite3-0 3.46.1-7+deb13u2 CVE-2026-11822, -11824 +# gzip 1.13-1+deb13u1 CVE-2026-41992 +# perl-base 5.40.1-6+deb13u1 CVE-2026-42497, -48962, -57432 +# libssh2-1t64 1.11.1-1+deb13u2 CVE-2026-58050 +# libpcre2-8-0 10.46-1~deb13u2 CVE-2026-86145, -89161 # Taken as a targeted --only-upgrade rather than by moving the digest: the newest -# published python:3.12-slim-trixie carries the same vulnerable version. The three -# packages are all built from openssl and are flagged separately, so all are named. -# Drop them once the base image ships 3.5.7-1~deb13u2 or later. +# published python:3.12-slim-trixie carries the same vulnerable versions. The three +# openssl packages are flagged separately, so all are named. +# Drop each one once the base image ships its fixed version. # hadolint ignore=DL3008 RUN apt-get update && apt-get install -y --no-install-recommends \ wget \ @@ -46,6 +50,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ python3-dev \ && apt-get install -y --no-install-recommends --only-upgrade \ util-linux libssl3t64 openssl openssl-provider-legacy \ + libsqlite3-0 gzip perl-base libssh2-1t64 libpcre2-8-0 \ && rm -rf /var/lib/apt/lists/* # Install PowerShell diff --git a/api/changelog.d/api-image-debian-cves.security.md b/api/changelog.d/api-image-debian-cves.security.md new file mode 100644 index 0000000000..2d8b0403ad --- /dev/null +++ b/api/changelog.d/api-image-debian-cves.security.md @@ -0,0 +1 @@ +`libsqlite3-0`, `gzip`, `perl-base` and `libpcre2-8-0` upgraded in the API container image, patching high Debian CVEs diff --git a/prowler/changelog.d/sdk-image-debian-cves.security.md b/prowler/changelog.d/sdk-image-debian-cves.security.md new file mode 100644 index 0000000000..50bd4186f3 --- /dev/null +++ b/prowler/changelog.d/sdk-image-debian-cves.security.md @@ -0,0 +1 @@ +`libsqlite3-0`, `gzip`, `perl-base`, `libssh2-1t64` and `libpcre2-8-0` upgraded in the SDK container image, patching nine high Debian CVEs From 8b265a83140d78f342a887359478d1dc9702246e Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:18:31 +0200 Subject: [PATCH 56/77] fix(ui): defer billing onboarding and add AWS button styling (#12803) --- .../aws-marketplace-button.added.md | 1 + .../defer-onboarding-on-billing.fixed.md | 1 + .../__tests__/onboarding-gate.test.tsx | 52 ++++++++++++++++++ ui/components/onboarding/onboarding-gate.tsx | 7 ++- ui/components/shadcn/button/button.tsx | 2 + ui/styles/globals.css | 3 + .../aws-marketplace-button-desktop.png | Bin 0 -> 12676 bytes .../aws-marketplace-button-mobile.png | Bin 0 -> 10992 bytes .../aws-marketplace-button-tablet.png | Bin 0 -> 11292 bytes 9 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 ui/changelog.d/aws-marketplace-button.added.md create mode 100644 ui/changelog.d/defer-onboarding-on-billing.fixed.md create mode 100644 ui/tests/onboarding/evidence/aws-marketplace-button-desktop.png create mode 100644 ui/tests/onboarding/evidence/aws-marketplace-button-mobile.png create mode 100644 ui/tests/onboarding/evidence/aws-marketplace-button-tablet.png diff --git a/ui/changelog.d/aws-marketplace-button.added.md b/ui/changelog.d/aws-marketplace-button.added.md new file mode 100644 index 0000000000..235112967f --- /dev/null +++ b/ui/changelog.d/aws-marketplace-button.added.md @@ -0,0 +1 @@ +AWS Marketplace button variant with outlined styling for light and dark themes diff --git a/ui/changelog.d/defer-onboarding-on-billing.fixed.md b/ui/changelog.d/defer-onboarding-on-billing.fixed.md new file mode 100644 index 0000000000..5afcc36bcc --- /dev/null +++ b/ui/changelog.d/defer-onboarding-on-billing.fixed.md @@ -0,0 +1 @@ +Automatic onboarding stays hidden on billing pages and remains available after leaving billing diff --git a/ui/components/onboarding/__tests__/onboarding-gate.test.tsx b/ui/components/onboarding/__tests__/onboarding-gate.test.tsx index 4198ba5846..9a5f7cf88e 100644 --- a/ui/components/onboarding/__tests__/onboarding-gate.test.tsx +++ b/ui/components/onboarding/__tests__/onboarding-gate.test.tsx @@ -9,9 +9,11 @@ import { OnboardingGate } from "../onboarding-gate"; const pushMock = vi.fn(); const armMock = vi.fn(); +const pathnameMock = vi.fn(); vi.mock("next/navigation", () => ({ useRouter: () => ({ push: pushMock, replace: vi.fn() }), + usePathname: () => pathnameMock(), })); vi.mock("@/store/onboarding-checkpoint", () => ({ @@ -30,12 +32,62 @@ describe("OnboardingGate", () => { window.localStorage.clear(); pushMock.mockClear(); armMock.mockClear(); + pathnameMock.mockReturnValue("/"); }); afterEach(() => { vi.restoreAllMocks(); }); + it.each(["/billing", "/billing/", "/billing/checkout"])( + "defers onboarding on %s without resolving it", + (pathname) => { + // Given + pathnameMock.mockReturnValue(pathname); + + // When + render(); + + // Then + expect( + screen.queryByRole("button", { name: /get started/i }), + ).not.toBeInTheDocument(); + expect(localStorageAdapter.get(addProviderTourId)).toBeNull(); + expect(armMock).not.toHaveBeenCalled(); + expect(pushMock).not.toHaveBeenCalled(); + }, + ); + + it("offers onboarding after leaving billing without remounting the gate", async () => { + // Given + pathnameMock.mockReturnValue("/billing"); + const { rerender } = render(); + + // When + pathnameMock.mockReturnValue("/"); + rerender(); + + // Then + expect( + await screen.findByRole("button", { name: /get started/i }), + ).toBeInTheDocument(); + expect(localStorageAdapter.get(addProviderTourId)).toBeNull(); + expect(armMock).not.toHaveBeenCalled(); + }); + + it("does not suppress onboarding on a route that only shares the billing prefix", async () => { + // Given + pathnameMock.mockReturnValue("/billing-settings"); + + // When + render(); + + // Then + expect( + await screen.findByRole("button", { name: /get started/i }), + ).toBeInTheDocument(); + }); + describe("when the user has no providers and no completion record", () => { it("shows the Welcome modal", async () => { render(); diff --git a/ui/components/onboarding/onboarding-gate.tsx b/ui/components/onboarding/onboarding-gate.tsx index 0161bffef4..f32d411938 100644 --- a/ui/components/onboarding/onboarding-gate.tsx +++ b/ui/components/onboarding/onboarding-gate.tsx @@ -1,6 +1,6 @@ "use client"; -import { useRouter } from "next/navigation"; +import { usePathname, useRouter } from "next/navigation"; import { useState } from "react"; import { getOrderedFlows, shouldStartOnboarding } from "@/lib/onboarding"; @@ -20,6 +20,10 @@ interface OnboardingGateProps { // via useSyncExternalStore — server renders nothing, no hydration mismatch. export function OnboardingGate({ hasProviders }: OnboardingGateProps) { const router = useRouter(); + const pathname = usePathname(); + // Billing must stay usable before onboarding; leaving it keeps the gate eligible. + const isBillingRoute = + pathname === "/billing" || pathname?.startsWith("/billing/"); // Gate forces only the first flow (`add-provider`); remaining flows come via checkpoint/replay. const flow = getOrderedFlows()[0] ?? null; @@ -32,6 +36,7 @@ export function OnboardingGate({ hasProviders }: OnboardingGateProps) { const activeFlow = flow && + !isBillingRoute && !resolvedThisSession && shouldStartOnboarding({ hasProviders, completionRecord }) ? flow diff --git a/ui/components/shadcn/button/button.tsx b/ui/components/shadcn/button/button.tsx index f34347507b..bc37c08bc9 100644 --- a/ui/components/shadcn/button/button.tsx +++ b/ui/components/shadcn/button/button.tsx @@ -19,6 +19,8 @@ const buttonVariants = cva( "border border-transparent bg-bg-fail text-white hover:bg-bg-fail/90 active:bg-bg-fail/80 focus-visible:ring-bg-fail/50", outline: "border border-border-neutral-secondary bg-bg-neutral-secondary hover:bg-bg-neutral-tertiary active:bg-border-neutral-tertiary text-text-neutral-primary focus-visible:ring-border-neutral-tertiary/50", + "aws-marketplace": + "border-2 border-button-aws-marketplace bg-transparent text-button-aws-marketplace font-semibold hover:bg-button-aws-marketplace/5 active:bg-button-aws-marketplace/10 focus-visible:ring-button-aws-marketplace", ghost: "border border-transparent text-text-neutral-primary hover:bg-bg-neutral-tertiary active:bg-border-neutral-secondary focus-visible:ring-border-neutral-secondary/50", link: "text-button-tertiary underline-offset-4 hover:text-button-tertiary-hover disabled:bg-transparent", diff --git a/ui/styles/globals.css b/ui/styles/globals.css index d879b452d2..c8f60e2992 100644 --- a/ui/styles/globals.css +++ b/ui/styles/globals.css @@ -92,6 +92,7 @@ --bg-button-tertiary-hover: var(--color-blue-500); --bg-button-tertiary-active: var(--color-indigo-600); --bg-button-disabled: var(--color-neutral-300); + --button-aws-marketplace: #232f3e; /* Radar Map */ --bg-radar-map: #b51c8033; @@ -218,6 +219,7 @@ --bg-button-tertiary-hover: var(--color-blue-400); --bg-button-tertiary-active: var(--color-blue-600); --bg-button-disabled: var(--color-neutral-700); + --button-aws-marketplace: var(--color-white); /* Neutral Map */ --bg-neutral-map: var(--color-gray-800); @@ -330,6 +332,7 @@ --color-button-tertiary-hover: var(--bg-button-tertiary-hover); --color-button-tertiary-active: var(--bg-button-tertiary-active); --color-button-disabled: var(--bg-button-disabled); + --color-button-aws-marketplace: var(--button-aws-marketplace); /* Input Colors */ --color-bg-input-primary: var(--bg-input-primary); diff --git a/ui/tests/onboarding/evidence/aws-marketplace-button-desktop.png b/ui/tests/onboarding/evidence/aws-marketplace-button-desktop.png new file mode 100644 index 0000000000000000000000000000000000000000..ddfac1e755a83a4ceb9be7926e1ff18a4b3ccae0 GIT binary patch literal 12676 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 literal 0 HcmV?d00001 diff --git a/ui/tests/onboarding/evidence/aws-marketplace-button-mobile.png b/ui/tests/onboarding/evidence/aws-marketplace-button-mobile.png new file mode 100644 index 0000000000000000000000000000000000000000..b0009e3b42bac2e7e4e92868619615683cdc59e2 GIT binary patch literal 10992 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 B*2(|? literal 0 HcmV?d00001 From 1b228d590b5faa92d9e0bbbab7d6c2c38d3cfeda Mon Sep 17 00:00:00 2001 From: Ethan Troy <63926014+ethanolivertroy@users.noreply.github.com> Date: Mon, 14 Sep 2026 05:53:19 -0400 Subject: [PATCH 57/77] feat(compliance): replace FedRAMP 20x pilot KSI with Consolidated Rules 2026.06.24.01 (#11701) Co-authored-by: Ethan Troy Co-authored-by: Cursor Co-authored-by: pedrooot --- .../compliance/fedramp_20x_ksi_low_aws.py | 46 - .../compliance/fedramp_20x_ksi_low_azure.py | 46 - .../compliance/fedramp_20x_ksi_low_gcp.py | 46 - .../changelog.d/fedramp-20x-ksi-2026.added.md | 1 + .../fedramp-20x-ksi-low-pilot.removed.md | 1 + .../aws/fedramp_20x_ksi_low_aws.json | 383 --- .../azure/fedramp_20x_ksi_low_azure.json | 305 --- prowler/compliance/fedramp_20x_ksi_2026.json | 2284 +++++++++++++++++ .../gcp/fedramp_20x_ksi_low_gcp.json | 294 --- 9 files changed, 2286 insertions(+), 1120 deletions(-) delete mode 100644 dashboard/compliance/fedramp_20x_ksi_low_aws.py delete mode 100644 dashboard/compliance/fedramp_20x_ksi_low_azure.py delete mode 100644 dashboard/compliance/fedramp_20x_ksi_low_gcp.py create mode 100644 prowler/changelog.d/fedramp-20x-ksi-2026.added.md create mode 100644 prowler/changelog.d/fedramp-20x-ksi-low-pilot.removed.md delete mode 100644 prowler/compliance/aws/fedramp_20x_ksi_low_aws.json delete mode 100644 prowler/compliance/azure/fedramp_20x_ksi_low_azure.json create mode 100644 prowler/compliance/fedramp_20x_ksi_2026.json delete mode 100644 prowler/compliance/gcp/fedramp_20x_ksi_low_gcp.json diff --git a/dashboard/compliance/fedramp_20x_ksi_low_aws.py b/dashboard/compliance/fedramp_20x_ksi_low_aws.py deleted file mode 100644 index 5ca220301f..0000000000 --- a/dashboard/compliance/fedramp_20x_ksi_low_aws.py +++ /dev/null @@ -1,46 +0,0 @@ -import warnings - -from dashboard.common_methods import get_section_containers_cis - -warnings.filterwarnings("ignore") - - -def get_table(data): - aux = data[ - [ - "REQUIREMENTS_ID", - "REQUIREMENTS_DESCRIPTION", - "REQUIREMENTS_ATTRIBUTES_SECTION", - "CHECKID", - "STATUS", - "REGION", - "ACCOUNTID", - "RESOURCEID", - ] - ].copy() - - # Shorten the long FedRAMP KSI descriptions for better display - ksi_short_names = { - "A secure cloud service offering will protect user data, control access, and apply zero trust principles": "Identity and Access Management", - "A secure cloud service offering will use cloud native architecture and design principles to enforce and enhance the Confidentiality, Integrity and Availability of the system": "Cloud Native Architecture", - "A secure cloud service provider will ensure that all system changes are properly documented and configuration baselines are updated accordingly": "Change Management", - "A secure cloud service provider will continuously educate their employees on cybersecurity measures, testing them regularly": "Cybersecurity Education", - "A secure cloud service offering will document, report, and analyze security incidents to ensure regulatory compliance and continuous security improvement": "Incident Reporting", - "A secure cloud service offering will monitor, log, and audit all important events, activity, and changes": "Monitoring, Logging, and Auditing", - "A secure cloud service offering will have intentional, organized, universal guidance for how every information resource, including personnel, is secured": "Policy and Inventory", - "A secure cloud service offering will define, maintain, and test incident response plan(s) and recovery capabilities to ensure minimal service disruption and data loss": "Recovery Planning", - "A secure cloud service offering will follow FedRAMP encryption policies, continuously verify information resource integrity, and restrict access to third-party information resources": "Service Configuration", - "A secure cloud service offering will understand, monitor, and manage supply chain risks from third-party information resources": "Third-Party Information Resources", - } - - # Replace long descriptions with short names - use contains for partial matching - if not aux.empty: - for long_desc, short_name in ksi_short_names.items(): - mask = aux["REQUIREMENTS_DESCRIPTION"].str.contains( - long_desc, na=False, regex=False - ) - aux.loc[mask, "REQUIREMENTS_DESCRIPTION"] = short_name - - return get_section_containers_cis( - aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION" - ) diff --git a/dashboard/compliance/fedramp_20x_ksi_low_azure.py b/dashboard/compliance/fedramp_20x_ksi_low_azure.py deleted file mode 100644 index 5ca220301f..0000000000 --- a/dashboard/compliance/fedramp_20x_ksi_low_azure.py +++ /dev/null @@ -1,46 +0,0 @@ -import warnings - -from dashboard.common_methods import get_section_containers_cis - -warnings.filterwarnings("ignore") - - -def get_table(data): - aux = data[ - [ - "REQUIREMENTS_ID", - "REQUIREMENTS_DESCRIPTION", - "REQUIREMENTS_ATTRIBUTES_SECTION", - "CHECKID", - "STATUS", - "REGION", - "ACCOUNTID", - "RESOURCEID", - ] - ].copy() - - # Shorten the long FedRAMP KSI descriptions for better display - ksi_short_names = { - "A secure cloud service offering will protect user data, control access, and apply zero trust principles": "Identity and Access Management", - "A secure cloud service offering will use cloud native architecture and design principles to enforce and enhance the Confidentiality, Integrity and Availability of the system": "Cloud Native Architecture", - "A secure cloud service provider will ensure that all system changes are properly documented and configuration baselines are updated accordingly": "Change Management", - "A secure cloud service provider will continuously educate their employees on cybersecurity measures, testing them regularly": "Cybersecurity Education", - "A secure cloud service offering will document, report, and analyze security incidents to ensure regulatory compliance and continuous security improvement": "Incident Reporting", - "A secure cloud service offering will monitor, log, and audit all important events, activity, and changes": "Monitoring, Logging, and Auditing", - "A secure cloud service offering will have intentional, organized, universal guidance for how every information resource, including personnel, is secured": "Policy and Inventory", - "A secure cloud service offering will define, maintain, and test incident response plan(s) and recovery capabilities to ensure minimal service disruption and data loss": "Recovery Planning", - "A secure cloud service offering will follow FedRAMP encryption policies, continuously verify information resource integrity, and restrict access to third-party information resources": "Service Configuration", - "A secure cloud service offering will understand, monitor, and manage supply chain risks from third-party information resources": "Third-Party Information Resources", - } - - # Replace long descriptions with short names - use contains for partial matching - if not aux.empty: - for long_desc, short_name in ksi_short_names.items(): - mask = aux["REQUIREMENTS_DESCRIPTION"].str.contains( - long_desc, na=False, regex=False - ) - aux.loc[mask, "REQUIREMENTS_DESCRIPTION"] = short_name - - return get_section_containers_cis( - aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION" - ) diff --git a/dashboard/compliance/fedramp_20x_ksi_low_gcp.py b/dashboard/compliance/fedramp_20x_ksi_low_gcp.py deleted file mode 100644 index 5ca220301f..0000000000 --- a/dashboard/compliance/fedramp_20x_ksi_low_gcp.py +++ /dev/null @@ -1,46 +0,0 @@ -import warnings - -from dashboard.common_methods import get_section_containers_cis - -warnings.filterwarnings("ignore") - - -def get_table(data): - aux = data[ - [ - "REQUIREMENTS_ID", - "REQUIREMENTS_DESCRIPTION", - "REQUIREMENTS_ATTRIBUTES_SECTION", - "CHECKID", - "STATUS", - "REGION", - "ACCOUNTID", - "RESOURCEID", - ] - ].copy() - - # Shorten the long FedRAMP KSI descriptions for better display - ksi_short_names = { - "A secure cloud service offering will protect user data, control access, and apply zero trust principles": "Identity and Access Management", - "A secure cloud service offering will use cloud native architecture and design principles to enforce and enhance the Confidentiality, Integrity and Availability of the system": "Cloud Native Architecture", - "A secure cloud service provider will ensure that all system changes are properly documented and configuration baselines are updated accordingly": "Change Management", - "A secure cloud service provider will continuously educate their employees on cybersecurity measures, testing them regularly": "Cybersecurity Education", - "A secure cloud service offering will document, report, and analyze security incidents to ensure regulatory compliance and continuous security improvement": "Incident Reporting", - "A secure cloud service offering will monitor, log, and audit all important events, activity, and changes": "Monitoring, Logging, and Auditing", - "A secure cloud service offering will have intentional, organized, universal guidance for how every information resource, including personnel, is secured": "Policy and Inventory", - "A secure cloud service offering will define, maintain, and test incident response plan(s) and recovery capabilities to ensure minimal service disruption and data loss": "Recovery Planning", - "A secure cloud service offering will follow FedRAMP encryption policies, continuously verify information resource integrity, and restrict access to third-party information resources": "Service Configuration", - "A secure cloud service offering will understand, monitor, and manage supply chain risks from third-party information resources": "Third-Party Information Resources", - } - - # Replace long descriptions with short names - use contains for partial matching - if not aux.empty: - for long_desc, short_name in ksi_short_names.items(): - mask = aux["REQUIREMENTS_DESCRIPTION"].str.contains( - long_desc, na=False, regex=False - ) - aux.loc[mask, "REQUIREMENTS_DESCRIPTION"] = short_name - - return get_section_containers_cis( - aux, "REQUIREMENTS_ID", "REQUIREMENTS_ATTRIBUTES_SECTION" - ) diff --git a/prowler/changelog.d/fedramp-20x-ksi-2026.added.md b/prowler/changelog.d/fedramp-20x-ksi-2026.added.md new file mode 100644 index 0000000000..5fae5bb4a2 --- /dev/null +++ b/prowler/changelog.d/fedramp-20x-ksi-2026.added.md @@ -0,0 +1 @@ +`FedRAMP-20x-KSI` universal compliance framework (`fedramp_20x_ksi_2026`) with the 46 Key Security Indicators from the FedRAMP Consolidated Rules 2026 mapped for AWS, Azure, GCP, Kubernetes and M365 diff --git a/prowler/changelog.d/fedramp-20x-ksi-low-pilot.removed.md b/prowler/changelog.d/fedramp-20x-ksi-low-pilot.removed.md new file mode 100644 index 0000000000..fdca7d54e5 --- /dev/null +++ b/prowler/changelog.d/fedramp-20x-ksi-low-pilot.removed.md @@ -0,0 +1 @@ +`fedramp_20x_ksi_low_aws`, `fedramp_20x_ksi_low_azure` and `fedramp_20x_ksi_low_gcp` FedRAMP 20x Phase One pilot frameworks, superseded by `fedramp_20x_ksi_2026` diff --git a/prowler/compliance/aws/fedramp_20x_ksi_low_aws.json b/prowler/compliance/aws/fedramp_20x_ksi_low_aws.json deleted file mode 100644 index 178f07d3a5..0000000000 --- a/prowler/compliance/aws/fedramp_20x_ksi_low_aws.json +++ /dev/null @@ -1,383 +0,0 @@ -{ - "Framework": "FedRAMP-20x-KSI-Low", - "Name": "FedRAMP 20x Key Security Indicators (KSIs) - Low Impact Level v25.05C", - "Version": "25.05C", - "Provider": "AWS", - "Description": "FedRAMP 20x Key Security Indicators (KSIs) Low Impact Level represent core security indicators for cloud service providers, focusing on automation, continuous monitoring, and cloud-native security principles per FedRAMP 20x Phase One pilot requirements for Low impact systems.", - "Requirements": [ - { - "Id": "ksi-cmt", - "Name": "KSI-CMT: Change Management", - "Description": "A secure cloud service provider will ensure that all system changes are properly documented and configuration baselines are updated accordingly", - "Attributes": [ - { - "ItemId": "ksi-cmt", - "Section": "Change Management", - "Service": "aws" - } - ], - "Checks": [ - "cloudtrail_multi_region_enabled", - "cloudtrail_log_file_validation_enabled", - "cloudtrail_s3_dataevents_read_enabled", - "cloudtrail_s3_dataevents_write_enabled", - "cloudwatch_changes_to_network_acls_alarm_configured", - "cloudwatch_changes_to_network_gateways_alarm_configured", - "cloudwatch_changes_to_network_route_tables_alarm_configured", - "cloudwatch_changes_to_vpcs_alarm_configured", - "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", - "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", - "cloudwatch_log_metric_filter_aws_organizations_changes", - "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", - "cloudwatch_log_metric_filter_policy_changes", - "cloudwatch_log_metric_filter_security_group_changes", - "config_recorder_all_regions_enabled", - "ec2_instance_managed_by_ssm", - "ec2_instance_older_than_specific_days", - "ssm_managed_compliant_patching" - ], - "ConfigRequirements": [ - { - "Check": "config_recorder_all_regions_enabled", - "ConfigKey": "mute_non_default_regions", - "Operator": "eq", - "Value": false - } - ] - }, - { - "Id": "ksi-cna", - "Name": "KSI-CNA: Cloud Native Architecture", - "Description": "A secure cloud service offering will use cloud native architecture and design principles to enforce and enhance the Confidentiality, Integrity and Availability of the system", - "Attributes": [ - { - "ItemId": "ksi-cna", - "Section": "Cloud Native Architecture", - "Service": "aws" - } - ], - "Checks": [ - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "autoscaling_group_capacity_rebalance_enabled", - "dynamodb_tables_pitr_enabled", - "dynamodb_table_deletion_protection_enabled", - "ec2_instance_imdsv2_enabled", - "ec2_networkacl_allow_ingress_any_port", - "ec2_securitygroup_default_restrict_traffic", - "ec2_securitygroup_allow_ingress_from_internet_to_any_port", - "eks_cluster_network_policy_enabled", - "eks_cluster_not_publicly_accessible", - "eks_cluster_private_nodes_enabled", - "eks_cluster_uses_a_supported_version", - "elb_cross_zone_load_balancing_enabled", - "elbv2_is_in_multiple_az", - "elbv2_waf_acl_attached", - "rds_instance_multi_az", - "rds_cluster_multi_az", - "vpc_subnet_no_public_ip_by_default", - "vpc_peering_routing_tables_with_least_privilege", - "ec2_confidential_workload_host_imdsv2_not_enforced" - ] - }, - { - "Id": "ksi-iam", - "Name": "KSI-IAM: Identity and Access Management", - "Description": "A secure cloud service offering will protect user data, control access, and apply zero trust principles", - "Attributes": [ - { - "ItemId": "ksi-iam", - "Section": "Identity and Access Management", - "Service": "aws" - } - ], - "Checks": [ - "iam_inline_policy_no_wildcard_marketplace_subscribe", - "iam_policy_no_wildcard_marketplace_subscribe", - "iam_administrator_access_with_mfa", - "iam_aws_attached_policy_no_administrative_privileges", - "iam_customer_attached_policy_no_administrative_privileges", - "iam_inline_policy_no_administrative_privileges", - "iam_no_custom_policy_permissive_role_assumption", - "iam_no_root_access_key", - "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_password_policy_lowercase", - "iam_password_policy_minimum_length_14", - "iam_password_policy_number", - "iam_password_policy_reuse_24", - "iam_password_policy_symbol", - "iam_password_policy_uppercase", - "iam_policy_attached_only_to_group_or_roles", - "iam_policy_no_full_access_to_cloudtrail", - "iam_policy_no_full_access_to_kms", - "iam_root_hardware_mfa_enabled", - "iam_root_mfa_enabled", - "iam_rotate_access_key_90_days", - "iam_role_access_not_stale_to_bedrock", - "iam_user_access_not_stale_to_bedrock", - "iam_user_access_not_stale_to_sagemaker", - "iam_user_accesskey_unused", - "iam_user_console_access_unused", - "iam_user_hardware_mfa_enabled", - "iam_user_mfa_enabled_console_access", - "iam_user_two_active_access_key", - "organizations_scp_check_deny_regions", - "organizations_opt_out_ai_services_policy" - ] - }, - { - "Id": "ksi-inr", - "Name": "KSI-INR: Incident Response", - "Description": "A secure cloud service offering will respond to incidents according to FedRAMP requirements and cloud service provider policies", - "Attributes": [ - { - "ItemId": "ksi-inr", - "Section": "Incident Response", - "Service": "aws" - } - ], - "Checks": [ - "guardduty_centrally_managed", - "guardduty_ec2_malware_protection_enabled", - "guardduty_eks_audit_log_enabled", - "guardduty_eks_runtime_monitoring_enabled", - "guardduty_is_enabled", - "guardduty_lambda_protection_enabled", - "guardduty_no_high_severity_findings", - "guardduty_rds_protection_enabled", - "guardduty_s3_protection_enabled", - "inspector2_is_enabled", - "inspector2_active_findings_exist", - "securityhub_enabled", - "sns_topics_kms_encryption_at_rest_enabled" - ], - "ConfigRequirements": [ - { - "Check": "guardduty_is_enabled", - "ConfigKey": "mute_non_default_regions", - "Operator": "eq", - "Value": false - }, - { - "Check": "securityhub_enabled", - "ConfigKey": "mute_non_default_regions", - "Operator": "eq", - "Value": false - } - ] - }, - { - "Id": "ksi-mla", - "Name": "KSI-MLA: Monitoring, Logging, and Auditing", - "Description": "A secure cloud service offering will monitor, log, and audit all important events, activity, and changes", - "Attributes": [ - { - "ItemId": "ksi-mla", - "Section": "Monitoring, Logging, and Auditing", - "Service": "aws" - } - ], - "Checks": [ - "apigateway_restapi_logging_enabled", - "cloudtrail_cloudwatch_logging_enabled", - "cloudtrail_kms_encryption_enabled", - "cloudtrail_log_file_validation_enabled", - "cloudtrail_multi_region_enabled", - "cloudtrail_s3_dataevents_read_enabled", - "cloudtrail_s3_dataevents_write_enabled", - "cloudwatch_log_group_kms_encryption_enabled", - "cloudwatch_log_group_retention_policy_specific_days_enabled", - "ecs_cluster_container_insights_enabled", - "eks_control_plane_logging_all_types_enabled", - "elb_logging_enabled", - "elbv2_logging_enabled", - "inspector2_is_enabled", - "opensearch_service_domains_cloudwatch_logging_enabled", - "rds_instance_enhanced_monitoring_enabled", - "rds_instance_integration_cloudwatch_logs", - "redshift_cluster_audit_logging", - "s3_bucket_server_access_logging_enabled", - "vpc_flow_logs_enabled", - "wafv2_webacl_logging_enabled", - "kms_key_enclave_debug_attestation_detected", - "kms_key_enclave_attestation_unknown_image" - ] - }, - { - "Id": "ksi-piy", - "Name": "KSI-PIY: Policy and Inventory", - "Description": "A secure cloud service offering will have intentional, organized, universal guidance for how every information resource, including personnel, is secured", - "Attributes": [ - { - "ItemId": "ksi-piy", - "Section": "Policy and Inventory", - "Service": "aws" - } - ], - "Checks": [ - "config_recorder_all_regions_enabled", - "config_recorder_using_aws_service_role", - "ec2_instance_managed_by_ssm", - "organizations_account_part_of_organizations", - "organizations_delegated_administrators", - "organizations_scp_check_deny_regions", - "organizations_tags_policies_enabled_and_attached", - "resourceexplorer2_indexes_found", - "trustedadvisor_premium_support_plan_subscribed" - ], - "ConfigRequirements": [ - { - "Check": "config_recorder_all_regions_enabled", - "ConfigKey": "mute_non_default_regions", - "Operator": "eq", - "Value": false - } - ] - }, - { - "Id": "ksi-rpl", - "Name": "KSI-RPL: Recovery Planning", - "Description": "A secure cloud service offering will define, maintain, and test incident response plan(s) and recovery capabilities to ensure minimal service disruption and data loss", - "Attributes": [ - { - "ItemId": "ksi-rpl", - "Section": "Recovery Planning", - "Service": "aws" - } - ], - "Checks": [ - "backup_plans_exist", - "backup_reportplans_exist", - "backup_vaults_exist", - "backup_vaults_encrypted", - "backup_recovery_point_encrypted", - "dlm_ebs_snapshot_lifecycle_policy_exists", - "dynamodb_tables_pitr_enabled", - "dynamodb_table_deletion_protection_enabled", - "efs_have_backup_enabled", - "fsx_file_system_copy_tags_to_backups_enabled", - "rds_instance_backup_enabled", - "rds_instance_deletion_protection", - "rds_cluster_deletion_protection", - "rds_snapshots_encrypted", - "redshift_cluster_automated_snapshot" - ] - }, - { - "Id": "ksi-svc", - "Name": "KSI-SVC: Service Configuration", - "Description": "A secure cloud service offering will follow FedRAMP encryption policies, continuously verify information resource integrity, and restrict access to third-party information resources", - "Attributes": [ - { - "ItemId": "ksi-svc", - "Section": "Service Configuration", - "Service": "aws" - } - ], - "Checks": [ - "acm_certificates_expiration_check", - "apigateway_restapi_cache_encrypted", - "cloudtrail_kms_encryption_enabled", - "dynamodb_accelerator_cluster_encryption_enabled", - "dynamodb_tables_kms_cmk_encryption_enabled", - "ec2_ebs_volume_encryption", - "ec2_ebs_default_encryption", - "efs_encryption_at_rest_enabled", - "eks_cluster_kms_cmk_encryption_in_secrets_enabled", - "elasticache_redis_cluster_rest_encryption_enabled", - "elasticache_redis_cluster_in_transit_encryption_enabled", - "elbv2_ssl_listeners", - "kinesis_stream_encrypted_at_rest", - "kms_cmk_rotation_enabled", - "kms_cmk_not_deleted_unintentionally", - "kms_key_not_publicly_accessible", - "rds_instance_storage_encrypted", - "rds_cluster_storage_encrypted", - "redshift_cluster_encrypted_at_rest", - "redshift_cluster_in_transit_encryption_enabled", - "s3_bucket_default_encryption", - "s3_bucket_secure_transport_policy", - "sagemaker_notebook_instance_encryption_enabled", - "sns_topics_kms_encryption_at_rest_enabled", - "sqs_queues_server_side_encryption_enabled", - "kms_key_enclave_attestation_not_enforced" - ] - }, - { - "Id": "ksi-tpr", - "Name": "KSI-TPR: Third-Party Information Resources", - "Description": "A secure cloud service offering will understand, monitor, and manage supply chain risks from third-party information resources", - "Attributes": [ - { - "ItemId": "ksi-tpr", - "Section": "Third-Party Information Resources", - "Service": "aws" - } - ], - "Checks": [ - "ecr_registry_scan_images_on_push_enabled", - "ecr_repositories_lifecycle_policy_enabled", - "ecr_repositories_not_publicly_accessible", - "ecr_repositories_scan_images_on_push_enabled", - "ecr_repositories_scan_vulnerabilities_in_latest_image", - "ecr_repositories_tag_immutability", - "inspector2_active_findings_exist", - "inspector2_is_enabled", - "awslambda_function_using_supported_runtimes", - "ssm_managed_compliant_patching", - "trustedadvisor_premium_support_plan_subscribed", - "guardduty_no_high_severity_findings" - ] - }, - { - "Id": "ksi-iam-07", - "Name": "KSI-IAM-07: Account Lifecycle Management", - "Description": "Securely manage the lifecycle and privileges of all accounts, roles, and groups", - "Attributes": [ - { - "ItemId": "ksi-iam-07", - "Section": "Identity and Access Management", - "Service": "aws" - } - ], - "Checks": [ - "iam_no_root_access_key", - "iam_policy_attached_only_to_group_or_roles", - "iam_rotate_access_key_90_days", - "iam_role_access_not_stale_to_bedrock", - "iam_user_access_not_stale_to_bedrock", - "iam_user_access_not_stale_to_sagemaker", - "iam_user_accesskey_unused", - "iam_user_console_access_unused", - "organizations_delegated_administrators" - ] - }, - { - "Id": "ksi-mla-07", - "Name": "KSI-MLA-07: Monitoring and Logging Inventory", - "Description": "Maintain a list of information resources and event types that will be monitored, logged, and audited", - "Attributes": [ - { - "ItemId": "ksi-mla-07", - "Section": "Monitoring, Logging, and Auditing", - "Service": "aws" - } - ], - "Checks": [ - "cloudtrail_multi_region_enabled", - "cloudwatch_log_group_retention_policy_specific_days_enabled", - "config_recorder_all_regions_enabled", - "inspector2_is_enabled", - "resourceexplorer2_indexes_found" - ], - "ConfigRequirements": [ - { - "Check": "config_recorder_all_regions_enabled", - "ConfigKey": "mute_non_default_regions", - "Operator": "eq", - "Value": false - } - ] - } - ] -} diff --git a/prowler/compliance/azure/fedramp_20x_ksi_low_azure.json b/prowler/compliance/azure/fedramp_20x_ksi_low_azure.json deleted file mode 100644 index 3e5ea9d956..0000000000 --- a/prowler/compliance/azure/fedramp_20x_ksi_low_azure.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "Framework": "FedRAMP-20x-KSI-Low", - "Name": "FedRAMP 20x Key Security Indicators (KSIs) - Low Impact Level v25.05C", - "Version": "25.05C", - "Provider": "Azure", - "Description": "FedRAMP 20x Key Security Indicators (KSIs) Low Impact Level represent core security indicators for cloud service providers, focusing on automation, continuous monitoring, and cloud-native security principles per FedRAMP 20x Phase One pilot requirements for Low impact systems.", - "Requirements": [ - { - "Id": "ksi-cmt", - "Name": "KSI-CMT: Change Management", - "Description": "A secure cloud service provider will ensure that all system changes are properly documented and configuration baselines are updated accordingly", - "Attributes": [ - { - "ItemId": "ksi-cmt", - "Section": "Change Management", - "Service": "azure" - } - ], - "Checks": [ - "monitor_alert_create_policy_assignment", - "monitor_alert_create_update_sqlserver_fr", - "monitor_alert_delete_sqlserver_fr", - "monitor_alert_create_update_nsg", - "monitor_alert_create_update_public_ip_address_rule", - "monitor_alert_create_update_security_solution", - "monitor_alert_delete_nsg", - "monitor_alert_delete_policy_assignment", - "monitor_alert_delete_public_ip_address_rule", - "monitor_alert_delete_security_solution", - "monitor_diagnostic_setting_with_appropriate_categories", - "defender_assessments_vm_endpoint_protection_installed" - ] - }, - { - "Id": "ksi-cna", - "Name": "KSI-CNA: Cloud Native Architecture", - "Description": "A secure cloud service offering will use cloud native architecture and design principles to enforce and enhance the Confidentiality, Integrity and Availability of the system", - "Attributes": [ - { - "ItemId": "ksi-cna", - "Section": "Cloud Native Architecture", - "Service": "azure" - } - ], - "Checks": [ - "aks_clusters_created_with_private_nodes", - "aks_clusters_public_access_disabled", - "aks_network_policy_enabled", - "app_function_vnet_integration_enabled", - "app_function_not_publicly_accessible", - "containerregistry_not_publicly_accessible", - "containerregistry_uses_private_link", - "cosmosdb_account_use_private_endpoints", - "cosmosdb_account_firewall_use_selected_networks", - "databricks_workspace_vnet_injection_enabled", - "keyvault_access_only_through_private_endpoints", - "keyvault_private_endpoints", - "network_bastion_host_exists", - "network_flow_log_captured_sent", - "network_ssh_internet_access_restricted", - "network_rdp_internet_access_restricted", - "network_watcher_enabled", - "storage_default_network_access_rule_is_denied" - ] - }, - { - "Id": "ksi-iam", - "Name": "KSI-IAM: Identity and Access Management", - "Description": "A secure cloud service offering will protect user data, control access, and apply zero trust principles", - "Attributes": [ - { - "ItemId": "ksi-iam", - "Section": "Identity and Access Management", - "Service": "azure" - } - ], - "Checks": [ - "entra_conditional_access_policy_require_mfa_for_management_api", - "entra_global_admin_in_less_than_five_users", - "entra_non_privileged_user_has_mfa", - "entra_policy_default_users_cannot_create_security_groups", - "entra_policy_ensure_default_user_cannot_create_apps", - "entra_policy_ensure_default_user_cannot_create_tenants", - "entra_policy_guest_invite_only_for_admin_roles", - "entra_policy_guest_users_access_restrictions", - "entra_policy_restricts_user_consent_for_apps", - "entra_policy_user_consent_for_verified_apps", - "entra_privileged_user_has_mfa", - "entra_security_defaults_enabled", - "entra_trusted_named_locations_exists", - "entra_user_with_vm_access_has_mfa", - "entra_users_cannot_create_microsoft_365_groups", - "iam_custom_role_has_permissions_to_administer_resource_locks", - "iam_role_user_access_admin_restricted", - "iam_subscription_roles_owner_custom_not_created", - "keyvault_rbac_enabled", - "app_function_identity_is_configured", - "app_function_identity_without_admin_privileges", - "app_ensure_auth_is_set_up", - "app_register_with_identity" - ] - }, - { - "Id": "ksi-inr", - "Name": "KSI-INR: Incident Response", - "Description": "A secure cloud service offering will respond to incidents according to FedRAMP requirements and cloud service provider policies", - "Attributes": [ - { - "ItemId": "ksi-inr", - "Section": "Incident Response", - "Service": "azure" - } - ], - "Checks": [ - "defender_attack_path_notifications_properly_configured", - "defender_ensure_notify_alerts_severity_is_high", - "defender_ensure_notify_emails_to_owners", - "defender_additional_email_configured_with_a_security_contact", - "defender_container_images_resolved_vulnerabilities", - "defender_container_images_scan_enabled", - "defender_ensure_defender_for_app_services_is_on", - "defender_ensure_defender_for_arm_is_on", - "defender_ensure_defender_for_azure_sql_databases_is_on", - "defender_ensure_defender_for_containers_is_on", - "defender_ensure_defender_for_cosmosdb_is_on", - "defender_ensure_defender_for_databases_is_on", - "defender_ensure_defender_for_dns_is_on", - "defender_ensure_defender_for_keyvault_is_on", - "defender_ensure_defender_for_os_relational_databases_is_on", - "defender_ensure_defender_for_server_is_on", - "defender_ensure_defender_for_sql_servers_is_on", - "defender_ensure_defender_for_storage_is_on", - "defender_ensure_iot_hub_defender_is_on", - "defender_ensure_wdatp_is_enabled" - ] - }, - { - "Id": "ksi-mla", - "Name": "KSI-MLA: Monitoring, Logging, and Auditing", - "Description": "A secure cloud service offering will monitor, log, and audit all important events, activity, and changes", - "Attributes": [ - { - "ItemId": "ksi-mla", - "Section": "Monitoring, Logging, and Auditing", - "Service": "azure" - } - ], - "Checks": [ - "app_function_application_insights_enabled", - "app_http_logs_enabled", - "appinsights_ensure_is_configured", - "defender_auto_provisioning_log_analytics_agent_vms_on", - "defender_auto_provisioning_vulnerabilty_assessments_machines_on", - "keyvault_logging_enabled", - "monitor_diagnostic_setting_with_appropriate_categories", - "monitor_diagnostic_settings_exists", - "network_flow_log_captured_sent", - "network_flow_log_more_than_90_days", - "network_watcher_enabled", - "postgresql_flexible_server_log_checkpoints_on", - "postgresql_flexible_server_log_connections_on", - "postgresql_flexible_server_log_disconnections_on", - "sqlserver_auditing_enabled", - "sqlserver_auditing_retention_90_days" - ] - }, - { - "Id": "ksi-piy", - "Name": "KSI-PIY: Policy and Inventory", - "Description": "A secure cloud service offering will have intentional, organized, universal guidance for how every information resource, including personnel, is secured", - "Attributes": [ - { - "ItemId": "ksi-piy", - "Section": "Policy and Inventory", - "Service": "azure" - } - ], - "Checks": [ - "defender_ensure_defender_for_containers_is_on", - "defender_ensure_defender_for_app_services_is_on", - "defender_ensure_defender_for_azure_sql_databases_is_on", - "defender_ensure_defender_for_keyvault_is_on", - "defender_ensure_defender_for_server_is_on", - "defender_ensure_defender_for_sql_servers_is_on", - "defender_ensure_defender_for_storage_is_on" - ] - }, - { - "Id": "ksi-rpl", - "Name": "KSI-RPL: Recovery Planning", - "Description": "A secure cloud service offering will define, maintain, and test incident response plan(s) and recovery capabilities to ensure minimal service disruption and data loss", - "Attributes": [ - { - "ItemId": "ksi-rpl", - "Section": "Recovery Planning", - "Service": "azure" - } - ], - "Checks": [ - "mysql_flexible_server_geo_redundant_backup_enabled", - "postgresql_flexible_server_geo_redundant_backup_enabled", - "storage_geo_redundant_enabled", - "storage_infrastructure_encryption_is_enabled", - "storage_ensure_soft_delete_is_enabled", - "vm_backup_enabled", - "vm_sufficient_daily_backup_retention_period" - ] - }, - { - "Id": "ksi-svc", - "Name": "KSI-SVC: Service Configuration", - "Description": "A secure cloud service offering will follow FedRAMP encryption policies, continuously verify information resource integrity, and restrict access to third-party information resources", - "Attributes": [ - { - "ItemId": "ksi-svc", - "Section": "Service Configuration", - "Service": "azure" - } - ], - "Checks": [ - "app_client_certificates_on", - "app_ensure_http_is_redirected_to_https", - "app_minimum_tls_version_12", - "containerregistry_admin_user_disabled", - "cosmosdb_account_use_aad_and_rbac", - "databricks_workspace_cmk_encryption_enabled", - "keyvault_key_expiration_set_in_non_rbac", - "keyvault_key_rotation_enabled", - "keyvault_non_rbac_secret_expiration_set", - "mysql_flexible_server_ssl_connection_enabled", - "mysql_flexible_server_minimum_tls_version_12", - "postgresql_flexible_server_enforce_ssl_enabled", - "defender_ensure_defender_for_sql_servers_is_on", - "sqlserver_tde_encrypted_with_cmk", - "sqlserver_tde_encryption_enabled", - "sqlserver_recommended_minimal_tls_version", - "storage_secure_transfer_required_is_enabled", - "storage_ensure_encryption_with_customer_managed_keys", - "storage_infrastructure_encryption_is_enabled", - "storage_ensure_minimum_tls_version_12", - "vm_ensure_attached_disks_encrypted_with_cmk" - ] - }, - { - "Id": "ksi-tpr", - "Name": "KSI-TPR: Third-Party Information Resources", - "Description": "A secure cloud service offering will understand, monitor, and manage supply chain risks from third-party information resources", - "Attributes": [ - { - "ItemId": "ksi-tpr", - "Section": "Third-Party Information Resources", - "Service": "azure" - } - ], - "Checks": [ - "app_ensure_java_version_is_latest", - "app_ensure_php_version_is_latest", - "app_ensure_python_version_is_latest", - "app_function_latest_runtime_version", - "defender_container_images_resolved_vulnerabilities", - "defender_container_images_scan_enabled", - "defender_ensure_system_updates_are_applied", - "defender_assessments_vm_endpoint_protection_installed" - ] - }, - { - "Id": "ksi-iam-07", - "Name": "KSI-IAM-07: Account Lifecycle Management", - "Description": "Securely manage the lifecycle and privileges of all accounts, roles, and groups", - "Attributes": [ - { - "ItemId": "ksi-iam-07", - "Section": "Identity and Access Management", - "Service": "azure" - } - ], - "Checks": [ - "entra_non_privileged_user_has_mfa", - "entra_privileged_user_has_mfa", - "entra_user_with_recent_sign_in", - "entra_user_with_vm_access_has_mfa", - "iam_custom_role_has_permissions_to_administer_resource_locks", - "iam_role_user_access_admin_restricted", - "app_function_identity_is_configured" - ] - }, - { - "Id": "ksi-mla-07", - "Name": "KSI-MLA-07: Monitoring and Logging Inventory", - "Description": "Maintain a list of information resources and event types that will be monitored, logged, and audited", - "Attributes": [ - { - "ItemId": "ksi-mla-07", - "Section": "Monitoring, Logging, and Auditing", - "Service": "azure" - } - ], - "Checks": [ - "monitor_diagnostic_setting_with_appropriate_categories", - "monitor_diagnostic_settings_exists", - "network_watcher_enabled" - ] - } - ] -} diff --git a/prowler/compliance/fedramp_20x_ksi_2026.json b/prowler/compliance/fedramp_20x_ksi_2026.json new file mode 100644 index 0000000000..b893675faf --- /dev/null +++ b/prowler/compliance/fedramp_20x_ksi_2026.json @@ -0,0 +1,2284 @@ +{ + "framework": "FedRAMP-20x-KSI", + "name": "FedRAMP 20x Key Security Indicators (KSI) 2026", + "version": "2026.07.14.01", + "description": "FedRAMP 20x Key Security Indicators (KSIs) from the FedRAMP Consolidated Rules for 2026 (release 2026.07.14.01, https://github.com/FedRAMP/rules). KSIs are outcome-oriented indicators that cloud service providers must demonstrate through automation and continuous monitoring; they do not replace the FedRAMP Rules (FRR) program obligations. Class A authorizations mandate a subset of seven KSIs via FRC-CLA-MFR; Classes B and C apply the full catalog within the Minimum Assessment Scope, with five indicators optional on Class B and required on Class C.", + "icon": "fedramp", + "attributes_metadata": [ + { + "key": "Theme", + "label": "Theme", + "type": "str", + "required": true, + "enum": [ + "KSI-CED: Cybersecurity Education", + "KSI-CMT: Change Management", + "KSI-CNA: Cloud Native Architecture", + "KSI-IAM: Identity and Access Management", + "KSI-INR: Incident Response", + "KSI-MLA: Monitoring, Logging, and Auditing", + "KSI-PIY: Policy and Inventory", + "KSI-RPL: Recovery Planning", + "KSI-SCR: Supply Chain Risk", + "KSI-SVC: Service Configuration" + ] + }, + { + "key": "NISTControls", + "label": "NIST SP 800-53 Controls", + "type": "str" + }, + { + "key": "ClassApplicability", + "label": "Class Applicability", + "type": "str", + "required": true, + "enum": [ + "Required for Classes B and C", + "Optional for Class B, required for Class C" + ] + } + ], + "outputs": { + "table_config": { + "group_by": "Theme" + }, + "pdf_config": { + "language": "en", + "primary_color": "#1B3A5C", + "secondary_color": "#2E6DA4", + "bg_color": "#F0F4FA", + "group_by_field": "Theme", + "sections": [ + "KSI-CED: Cybersecurity Education", + "KSI-CMT: Change Management", + "KSI-CNA: Cloud Native Architecture", + "KSI-IAM: Identity and Access Management", + "KSI-INR: Incident Response", + "KSI-MLA: Monitoring, Logging, and Auditing", + "KSI-PIY: Policy and Inventory", + "KSI-RPL: Recovery Planning", + "KSI-SCR: Supply Chain Risk", + "KSI-SVC: Service Configuration" + ], + "section_short_names": { + "KSI-CED: Cybersecurity Education": "KSI-CED", + "KSI-CMT: Change Management": "KSI-CMT", + "KSI-CNA: Cloud Native Architecture": "KSI-CNA", + "KSI-IAM: Identity and Access Management": "KSI-IAM", + "KSI-INR: Incident Response": "KSI-INR", + "KSI-MLA: Monitoring, Logging, and Auditing": "KSI-MLA", + "KSI-PIY: Policy and Inventory": "KSI-PIY", + "KSI-RPL: Recovery Planning": "KSI-RPL", + "KSI-SCR: Supply Chain Risk": "KSI-SCR", + "KSI-SVC: Service Configuration": "KSI-SVC" + }, + "charts": [ + { + "id": "theme_compliance", + "type": "horizontal_bar", + "group_by": "Theme", + "title": "Compliance Score by KSI Theme", + "y_label": "Theme", + "x_label": "Compliance %", + "value_source": "compliance_percent", + "color_mode": "by_value" + } + ], + "filter": { + "only_failed": true, + "include_manual": false + } + } + }, + "requirements": [ + { + "id": "KSI-CED-RAT", + "name": "Reviewing All Training", + "description": "The effectiveness of relevant cybersecurity education and training is persistently reviewed, including at least general training for all employees, role-specific training for employees in high risk roles, training for development and engineering staff on secure software delivery, and training for staff involved with incident response or disaster recovery.", + "attributes": { + "Theme": "KSI-CED: Cybersecurity Education", + "NISTControls": "CP-3, IR-2, PS-6, AT-2, AT-2.2, AT-2.3, AT-3.5, AT-4, IR-2.3, AT-3, SR-11.1", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-CMT-LMC", + "name": "Logging Changes", + "description": "Modifications to the cloud service offering are logged and monitored.", + "attributes": { + "Theme": "KSI-CMT: Change Management", + "NISTControls": "AU-2, CM-3, CM-3.2, CM-4.2, CM-6, CM-8.3, MA-2", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "cloudtrail_cloudwatch_logging_enabled", + "cloudtrail_multi_region_enabled", + "cloudtrail_multi_region_enabled_logging_management_events", + "cloudtrail_s3_dataevents_write_enabled", + "cloudwatch_changes_to_network_acls_alarm_configured", + "cloudwatch_changes_to_network_gateways_alarm_configured", + "cloudwatch_changes_to_network_route_tables_alarm_configured", + "cloudwatch_changes_to_vpcs_alarm_configured", + "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", + "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", + "cloudwatch_log_metric_filter_aws_organizations_changes", + "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", + "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", + "cloudwatch_log_metric_filter_policy_changes", + "cloudwatch_log_metric_filter_security_group_changes", + "config_recorder_all_regions_enabled" + ], + "azure": [ + "monitor_alert_create_policy_assignment", + "monitor_alert_create_update_nsg", + "monitor_alert_create_update_public_ip_address_rule", + "monitor_alert_create_update_security_solution", + "monitor_alert_create_update_sqlserver_fr", + "monitor_alert_delete_nsg", + "monitor_alert_delete_policy_assignment", + "monitor_alert_delete_public_ip_address_rule", + "monitor_alert_delete_security_solution", + "monitor_alert_delete_sqlserver_fr", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists" + ], + "gcp": [ + "iam_audit_logs_enabled", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_compute_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" + ], + "kubernetes": [ + "apiserver_audit_log_path_set" + ], + "m365": [ + "exchange_organization_mailbox_auditing_enabled", + "exchange_user_mailbox_auditing_enabled", + "purview_audit_log_search_enabled" + ] + }, + "config_requirements": [ + { + "Check": "exchange_user_mailbox_auditing_enabled", + "ConfigKey": "audit_log_age", + "Operator": "gte", + "Value": 90, + "Provider": "m365" + }, + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-CMT-RMV", + "name": "Redeploying vs Modifying", + "description": "Changes to machine-based information resources are executed through the redeployment of version controlled resources rather than direct modification wherever reasonable.", + "attributes": { + "Theme": "KSI-CMT: Change Management", + "NISTControls": "CM-2, CM-3, CM-5, CM-6, CM-7, CM-8.1, SI-3", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "autoscaling_group_using_ec2_launch_template", + "ecs_task_definitions_containers_readonly_access" + ], + "azure": [], + "gcp": [], + "kubernetes": [ + "apiserver_always_pull_images_plugin", + "core_image_tag_fixed", + "core_readonly_root_filesystem_enabled" + ], + "m365": [] + } + }, + { + "id": "KSI-CMT-RVP", + "name": "Reviewing Change Procedures", + "description": "The effectiveness of documented change management procedures is persistently reviewed.", + "attributes": { + "Theme": "KSI-CMT: Change Management", + "NISTControls": "CM-3, CM-3.2, CM-3.4, CM-5, CM-7.1, CM-9", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-CMT-VTD", + "name": "Validating Throughout Deployment", + "description": "Persistent testing and validation of changes throughout deployment is automated.", + "attributes": { + "Theme": "KSI-CMT: Change Management", + "NISTControls": "CM-3, CM-3.2, CM-4.2, SI-2", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-CNA-DFP", + "name": "Defining Functionality and Privileges", + "description": "The functionality and privileges for infrastructure and services are strictly defined.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "CM-2, SI-3", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "ec2_instance_imdsv2_enabled", + "ecs_task_definitions_host_namespace_not_shared", + "ecs_task_definitions_host_networking_mode_users", + "ecs_task_definitions_no_privileged_containers", + "organizations_scp_check_deny_regions", + "sagemaker_notebook_instance_root_access_disabled" + ], + "azure": [], + "gcp": [ + "cloudstorage_bucket_uniform_bucket_level_access" + ], + "kubernetes": [ + "apiserver_auth_mode_include_node", + "apiserver_auth_mode_include_rbac", + "apiserver_auth_mode_not_always_allow", + "apiserver_namespace_lifecycle_plugin", + "apiserver_node_restriction_plugin", + "apiserver_security_context_deny_plugin", + "apiserver_service_account_plugin" + ], + "m365": [ + "entra_admin_portals_access_restriction", + "entra_all_apps_conditional_access_coverage", + "entra_conditional_access_policy_app_enforced_restrictions", + "entra_conditional_access_policy_approved_client_app_required_for_mobile", + "entra_conditional_access_policy_device_code_flow_blocked", + "entra_managed_device_required_for_authentication" + ] + } + }, + { + "id": "KSI-CNA-EIS", + "name": "Enforcing Intended State", + "description": "Automated services are used to persistently assess the security of all machine-based information resources and automatically enforce their intended operational state.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "CA-2.1, CA-7.1", + "ClassApplicability": "Optional for Class B, required for Class C" + }, + "checks": { + "aws": [ + "config_delegated_admin_and_org_aggregator_all_regions", + "config_recorder_all_regions_enabled", + "securityhub_enabled", + "ssm_managed_compliant_patching" + ], + "azure": [ + "defender_ensure_defender_cspm_is_on", + "policy_ensure_asc_enforcement_enabled" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + }, + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + }, + { + "Check": "config_delegated_admin_and_org_aggregator_all_regions", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-CNA-IBP", + "name": "Implementing Best Practices", + "description": "The use and configuration of third-party machine-based information resources is persistently compared against the original provider's best practices and guidance.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "AC-17.3, CM-2, PL-10", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "awslambda_function_using_supported_runtimes", + "ec2_instance_with_outdated_ami", + "ecs_service_fargate_latest_platform_version", + "eks_cluster_uses_a_supported_version", + "kafka_cluster_uses_latest_version", + "opensearch_service_domains_updated_to_the_latest_service_software_version", + "rds_instance_deprecated_engine_version", + "wellarchitected_workload_no_high_or_medium_risks" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [ + "defender_strict_preset_security_policy_enabled" + ] + }, + "config_requirements": [ + { + "Check": "awslambda_function_using_supported_runtimes", + "ConfigKey": "obsolete_lambda_runtimes", + "Operator": "superset", + "Value": [ + "java8", + "go1.x", + "provided", + "python3.6", + "python2.7", + "python3.7", + "python3.8", + "nodejs4.3", + "nodejs4.3-edge", + "nodejs6.10", + "nodejs", + "nodejs8.10", + "nodejs10.x", + "nodejs12.x", + "nodejs14.x", + "nodejs16.x", + "dotnet5.0", + "dotnet6", + "dotnet7", + "dotnetcore1.0", + "dotnetcore2.0", + "dotnetcore2.1", + "dotnetcore3.1", + "ruby2.5", + "ruby2.7" + ], + "Provider": "aws" + } + ] + }, + { + "id": "KSI-CNA-MAT", + "name": "Minimizing Attack Surface", + "description": "Machine-based information resources are persistently reviewed to ensure they have a minimal attack surface and that lateral movement is minimized if compromised.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "AC-17.3, AC-18.1, AC-18.3, AC-20.1, CA-9, SC-7.3, SC-7.4, SC-7.5, SC-7.8, SC-8, SC-10, SI-10, SI-11, SI-16", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "apigateway_restapi_public", + "appstream_fleet_default_internet_access_disabled", + "autoscaling_group_launch_configuration_no_public_ip", + "awslambda_function_not_publicly_accessible", + "awslambda_function_url_public", + "codebuild_project_not_publicly_accessible", + "dms_instance_no_public_access", + "ec2_instance_internet_facing_with_instance_profile", + "ec2_instance_public_ip", + "ec2_instance_uses_single_eni", + "ec2_launch_template_no_public_ip", + "ecs_service_no_assign_public_ip", + "ecs_task_set_no_assign_public_ip", + "efs_mount_target_not_publicly_accessible", + "eks_cluster_not_publicly_accessible", + "eks_cluster_private_nodes_enabled", + "elasticache_cluster_uses_public_subnet", + "elb_internet_facing", + "elbv2_internet_facing", + "emr_cluster_account_public_block_enabled", + "emr_cluster_master_nodes_no_public_ip", + "emr_cluster_publicly_accesible", + "kafka_cluster_is_public", + "lightsail_database_public", + "lightsail_instance_public", + "mq_broker_not_publicly_accessible", + "neptune_cluster_uses_public_subnet", + "opensearch_service_domains_not_publicly_accessible", + "rds_instance_no_public_access", + "redshift_cluster_public_access", + "sagemaker_models_network_isolation_enabled", + "sagemaker_notebook_instance_without_direct_internet_access_configured", + "sagemaker_training_jobs_network_isolation_enabled", + "vpc_peering_routing_tables_with_least_privilege", + "vpc_subnet_no_public_ip_by_default" + ], + "azure": [ + "aisearch_service_not_publicly_accessible", + "aks_clusters_created_with_private_nodes", + "aks_clusters_public_access_disabled", + "app_function_ftps_deployment_disabled", + "app_function_not_publicly_accessible", + "containerregistry_not_publicly_accessible", + "cosmosdb_account_public_network_access_disabled", + "databricks_workspace_no_public_ip_enabled", + "databricks_workspace_public_network_access_disabled", + "postgresql_flexible_server_allow_access_services_disabled", + "sqlserver_unrestricted_inbound_access", + "storage_account_public_network_access_disabled", + "storage_default_network_access_rule_is_denied" + ], + "gcp": [ + "cloudfunction_function_not_publicly_accessible", + "cloudsql_instance_private_ip_assignment", + "cloudsql_instance_public_access", + "cloudsql_instance_public_ip", + "cloudsql_instance_sqlserver_cross_db_ownership_chaining_flag", + "cloudsql_instance_sqlserver_external_scripts_enabled_flag", + "cloudsql_instance_sqlserver_remote_access_flag", + "compute_instance_block_project_wide_ssh_keys_disabled", + "compute_instance_ip_forwarding_is_enabled", + "compute_instance_public_ip", + "compute_instance_single_network_interface" + ], + "kubernetes": [ + "apiserver_anonymous_requests", + "apiserver_disable_profiling", + "apiserver_no_always_admit_plugin", + "controllermanager_disable_profiling", + "core_minimize_admission_windows_hostprocess_containers", + "core_minimize_allowPrivilegeEscalation_containers", + "core_minimize_containers_added_capabilities", + "core_minimize_containers_capabilities_assigned", + "core_minimize_hostpath_volume_mounts", + "core_minimize_net_raw_capability_admission", + "core_minimize_privileged_containers", + "core_minimize_root_containers_admission", + "kubelet_disable_read_only_port", + "scheduler_profiling" + ], + "m365": [ + "entra_device_registration_laps_enabled", + "exchange_roles_assignment_policy_addins_disabled", + "sharepoint_onedrive_sync_restricted_unmanaged_devices", + "teams_email_sending_to_channel_disabled", + "teams_external_file_sharing_restricted", + "teams_external_users_cannot_start_conversations", + "teams_meeting_anonymous_user_join_disabled", + "teams_meeting_anonymous_user_start_disabled", + "teams_meeting_chat_anonymous_users_disabled", + "teams_meeting_dial_in_lobby_bypass_disabled", + "teams_meeting_external_chat_disabled", + "teams_meeting_external_control_disabled", + "teams_meeting_external_lobby_bypass_disabled", + "teams_meeting_presenters_restricted", + "teams_meeting_recording_disabled", + "teams_unmanaged_communication_disabled" + ] + } + }, + { + "id": "KSI-CNA-OFA", + "name": "Optimizing for Availability", + "description": "Machine-based information resources are persistently reviewed to ensure they are appropriately optimized for high availability and rapid recovery.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "autoscaling_group_capacity_rebalance_enabled", + "autoscaling_group_elb_health_check_enabled", + "autoscaling_group_multiple_az", + "autoscaling_group_multiple_instance_types", + "awslambda_function_vpc_multi_az", + "cloudfront_distributions_multiple_origin_failover_configured", + "directconnect_connection_redundancy", + "directconnect_virtual_interface_redundancy", + "dms_instance_multi_az_enabled", + "documentdb_cluster_multi_az_enabled", + "dynamodb_accelerator_cluster_multi_az", + "dynamodb_table_autoscaling_enabled", + "dynamodb_table_deletion_protection_enabled", + "dynamodb_tables_pitr_enabled", + "efs_multi_az_enabled", + "elasticache_redis_cluster_automatic_failover_enabled", + "elasticache_redis_cluster_multi_az_enabled", + "elb_cross_zone_load_balancing_enabled", + "elb_is_in_multiple_az", + "elbv2_cross_zone_load_balancing_enabled", + "elbv2_is_in_multiple_az", + "eventbridge_global_endpoint_event_replication_enabled", + "fsx_windows_file_system_multi_az_enabled", + "mq_broker_active_deployment_mode", + "mq_broker_cluster_deployment_mode", + "neptune_cluster_multi_az", + "networkfirewall_multi_az", + "opensearch_service_domains_fault_tolerant_data_nodes", + "opensearch_service_domains_fault_tolerant_master_nodes", + "rds_cluster_multi_az", + "rds_instance_multi_az", + "redshift_cluster_multi_az_enabled", + "sagemaker_endpoint_config_prod_variant_instances", + "storagegateway_gateway_fault_tolerant", + "vpc_endpoint_multi_az_enabled", + "vpc_subnet_different_az", + "vpc_vpn_connection_tunnels_up" + ], + "azure": [ + "cosmosdb_account_automatic_failover_enabled", + "mysql_flexible_server_high_availability_enabled", + "postgresql_flexible_server_high_availability_enabled", + "vm_backup_enabled", + "vm_scaleset_associated_with_load_balancer" + ], + "gcp": [ + "cloudsql_instance_high_availability_enabled", + "compute_instance_automatic_restart_enabled", + "compute_instance_group_autohealing_enabled", + "compute_instance_group_load_balancer_attached", + "compute_instance_group_multiple_zones", + "compute_instance_on_host_maintenance_migrate", + "compute_instance_preemptible_vm_disabled" + ], + "kubernetes": [ + "core_liveness_probe_configured", + "core_readiness_probe_configured" + ], + "m365": [] + }, + "config_requirements": [ + { + "Check": "awslambda_function_vpc_multi_az", + "ConfigKey": "lambda_min_azs", + "Operator": "gte", + "Value": 2, + "Provider": "aws" + }, + { + "Check": "elb_is_in_multiple_az", + "ConfigKey": "elb_min_azs", + "Operator": "gte", + "Value": 2, + "Provider": "aws" + }, + { + "Check": "compute_instance_group_multiple_zones", + "ConfigKey": "mig_min_zones", + "Operator": "gte", + "Value": 2, + "Provider": "gcp" + } + ] + }, + { + "id": "KSI-CNA-RNT", + "name": "Restricting Network Traffic", + "description": "Machine-based information resources are persistently reviewed to ensure they are appropriately configured to limit inbound and outbound network traffic.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "AC-17.3, CA-9, CM-7.1, SC-7.5, SI-8", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "ec2_networkacl_allow_ingress_any_port", + "ec2_networkacl_allow_ingress_tcp_port_22", + "ec2_networkacl_allow_ingress_tcp_port_3389", + "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_any_port_from_ip", + "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", + "ec2_securitygroup_allow_wide_open_public_ipv4", + "ec2_securitygroup_default_restrict_traffic" + ], + "azure": [ + "network_http_internet_access_restricted", + "network_rdp_internet_access_restricted", + "network_ssh_internet_access_restricted", + "network_udp_internet_access_restricted" + ], + "gcp": [ + "compute_firewall_rdp_access_from_the_internet_allowed", + "compute_firewall_ssh_access_from_the_internet_allowed", + "compute_network_default_in_use" + ], + "kubernetes": [ + "apiserver_deny_service_external_ips", + "controllermanager_bind_address", + "core_minimize_admission_hostport_containers", + "core_minimize_hostNetwork_containers", + "scheduler_bind_address" + ], + "m365": [] + }, + "config_requirements": [ + { + "Check": "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ConfigKey": "ec2_allowed_interface_types", + "Operator": "subset", + "Value": [ + "api_gateway_managed", + "vpc_endpoint" + ], + "Provider": "aws" + }, + { + "Check": "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ConfigKey": "ec2_allowed_instance_owners", + "Operator": "subset", + "Value": [ + "amazon-elb" + ], + "Provider": "aws" + }, + { + "Check": "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", + "ConfigKey": "ec2_high_risk_ports", + "Operator": "superset", + "Value": [ + 25, + 110, + 135, + 143, + 445, + 3000, + 4333, + 5000, + 5500, + 8080, + 8088 + ], + "Provider": "aws" + } + ] + }, + { + "id": "KSI-CNA-RVP", + "name": "Reviewing Protections", + "description": "The effectiveness of protection against denial of service attacks and other unwanted activity for machine-based information resources is persistently reviewed.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "SC-5, SI-8, SI-8.2", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "apigateway_restapi_waf_acl_attached", + "cloudfront_distributions_using_waf", + "cognito_user_pool_waf_acl_attached", + "elb_desync_mitigation_mode", + "elbv2_desync_mitigation_mode", + "elbv2_waf_acl_attached", + "fms_policy_compliant", + "shield_advanced_protection_in_associated_elastic_ips", + "shield_advanced_protection_in_classic_load_balancers", + "shield_advanced_protection_in_cloudfront_distributions", + "shield_advanced_protection_in_global_accelerators", + "shield_advanced_protection_in_internet_facing_load_balancers", + "shield_advanced_protection_in_route53_hosted_zones", + "waf_global_rule_with_conditions", + "waf_global_rulegroup_not_empty", + "waf_global_webacl_with_rules", + "waf_regional_rule_with_conditions", + "waf_regional_rulegroup_not_empty", + "waf_regional_webacl_with_rules", + "wafv2_webacl_with_rules" + ], + "azure": [ + "network_vnet_ddos_protection_enabled", + "postgresql_flexible_server_connection_throttling_on" + ], + "gcp": [], + "kubernetes": [ + "apiserver_event_rate_limit", + "apiserver_request_timeout_set", + "core_cpu_limits_set", + "core_memory_limits_set", + "kubelet_streaming_connection_timeout" + ], + "m365": [] + } + }, + { + "id": "KSI-CNA-ULN", + "name": "Using Logical Networking", + "description": "Logical networking and related capabilities are used and persistently reviewed to enforce traffic flow controls.", + "attributes": { + "Theme": "KSI-CNA: Cloud Native Architecture", + "NISTControls": "AC-12, AC-17.3, CA-9, SC-4, SC-7, SC-7.7, SC-8, SC-10", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "eks_cluster_network_policy_enabled", + "eks_cluster_vpc_cni_network_policy_enforced", + "networkfirewall_in_all_vpc", + "networkfirewall_policy_default_action_fragmented_packets", + "networkfirewall_policy_default_action_full_packets", + "networkfirewall_policy_rule_group_associated", + "vpc_endpoint_connections_trust_boundaries", + "vpc_endpoint_services_allowed_principals_trust_boundaries", + "vpc_subnet_separate_private_public" + ], + "azure": [ + "aks_network_policy_enabled", + "network_bastion_host_exists", + "network_subnet_nsg_associated" + ], + "gcp": [ + "cloudfunction_function_inside_vpc", + "cloudstorage_uses_vpc_service_controls" + ], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-IAM-AAM", + "name": "Automating Account Management", + "description": "The lifecycle and privileges of all accounts, roles, and groups are securely managed using automation.", + "attributes": { + "Theme": "KSI-IAM: Identity and Access Management", + "NISTControls": "AC-2.2, AC-2.3, AC-2.13, AC-6.7, IA-4.4, IA-12, IA-12.2, IA-12.3, IA-12.5", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "iam_no_root_access_key", + "iam_root_credentials_management_enabled", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", + "iam_user_no_setup_initial_access_key", + "organizations_delegated_administrators" + ], + "azure": [ + "entra_user_with_recent_sign_in" + ], + "gcp": [ + "iam_service_account_unused" + ], + "kubernetes": [], + "m365": [ + "entra_dynamic_group_for_guests_created" + ] + }, + "config_requirements": [ + { + "Check": "iam_user_accesskey_unused", + "ConfigKey": "max_unused_access_keys_days", + "Operator": "lte", + "Value": 45, + "Provider": "aws" + }, + { + "Check": "iam_user_console_access_unused", + "ConfigKey": "max_console_access_days", + "Operator": "lte", + "Value": 45, + "Provider": "aws" + }, + { + "Check": "iam_service_account_unused", + "ConfigKey": "max_unused_account_days", + "Operator": "lte", + "Value": 180, + "Provider": "gcp" + } + ] + }, + { + "id": "KSI-IAM-APM", + "name": "Adopting Passwordless Methods", + "description": "Secure passwordless methods are used for user authentication and authorization when feasible, otherwise strong passwords with phishing-resistant MFA is used.", + "attributes": { + "Theme": "KSI-IAM: Identity and Access Management", + "NISTControls": "AC-3, IA-5.1, IA-5.2, IA-5.6, IA-6, AC-2, IA-2, IA-2.1, IA-2.2, IA-2.8, IA-5, IA-8, SC-23", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "cognito_user_pool_password_policy_lowercase", + "cognito_user_pool_password_policy_minimum_length_14", + "cognito_user_pool_password_policy_number", + "cognito_user_pool_password_policy_symbol", + "cognito_user_pool_password_policy_uppercase", + "iam_password_policy_lowercase", + "iam_password_policy_minimum_length_14", + "iam_password_policy_number", + "iam_password_policy_reuse_24", + "iam_password_policy_symbol", + "iam_password_policy_uppercase", + "iam_root_hardware_mfa_enabled", + "iam_user_hardware_mfa_enabled" + ], + "azure": [ + "vm_linux_enforce_ssh_authentication" + ], + "gcp": [], + "kubernetes": [], + "m365": [ + "entra_admin_users_phishing_resistant_mfa_enabled", + "entra_break_glass_account_fido2_security_key_registered", + "entra_password_protection_custom_banned_list_enforced", + "entra_password_protection_on_premises_enforced" + ] + } + }, + { + "id": "KSI-IAM-ELP", + "name": "Ensuring Least Privilege", + "description": "Identity and access management measures are used and persistently reviewed to ensure each user or device can only access the resources they need.", + "attributes": { + "Theme": "KSI-IAM: Identity and Access Management", + "NISTControls": "AC-2.5, AC-2.6, AC-3, AC-4, AC-6, AC-12, AC-14, AC-17, AC-17.1, AC-17.2, AC-17.3, AC-20, AC-20.1, CM-2.7, CM-9, IA-2, IA-3, IA-4, IA-4.4, IA-5.2, IA-5.6, IA-11, PS-2, PS-3, PS-4, PS-5, PS-6, SC-4, SC-20, SC-21, SC-22, SC-23, SC-39, SI-3", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "accessanalyzer_enabled", + "accessanalyzer_enabled_without_findings", + "bedrock_agent_role_least_privilege", + "bedrock_agent_role_not_shared_across_agents", + "efs_access_point_enforce_root_directory", + "efs_access_point_enforce_user_identity", + "iam_role_access_not_stale_to_bedrock", + "iam_user_access_not_stale_to_bedrock", + "iam_user_access_not_stale_to_sagemaker", + "opensearch_service_domains_access_control_enabled" + ], + "azure": [ + "aks_cluster_rbac_enabled", + "entra_policy_default_users_cannot_create_security_groups", + "entra_policy_ensure_default_user_cannot_create_apps", + "entra_policy_ensure_default_user_cannot_create_tenants", + "entra_policy_guest_invite_only_for_admin_roles", + "entra_policy_guest_users_access_restrictions", + "entra_policy_restricts_user_consent_for_apps", + "entra_policy_user_consent_for_verified_apps", + "entra_users_cannot_create_microsoft_365_groups", + "keyvault_rbac_enabled" + ], + "gcp": [ + "compute_instance_default_service_account_in_use", + "compute_instance_default_service_account_in_use_with_full_api_access" + ], + "kubernetes": [ + "kubelet_authorization_mode", + "rbac_cluster_admin_usage", + "rbac_minimize_csr_approval_access", + "rbac_minimize_node_proxy_subresource_access", + "rbac_minimize_pod_creation_access", + "rbac_minimize_pv_creation_access", + "rbac_minimize_secret_access", + "rbac_minimize_service_account_token_creation", + "rbac_minimize_webhook_config_access", + "rbac_minimize_wildcard_use_roles" + ], + "m365": [ + "admincenter_users_admins_reduced_license_footprint", + "admincenter_users_between_two_and_four_global_admins", + "entra_access_review_guest_users_configured", + "entra_access_review_privileged_roles_configured", + "entra_admin_users_cloud_only", + "entra_conditional_access_policy_groups_management_restricted", + "entra_device_registration_global_admins_not_local_admins", + "entra_device_registration_registering_user_not_local_admin", + "entra_policy_default_user_cannot_create_m365_groups", + "entra_policy_default_user_cannot_create_security_groups", + "entra_policy_guest_invite_only_for_admin_roles", + "entra_policy_guest_users_access_restrictions" + ] + }, + "config_requirements": [ + { + "Check": "iam_user_access_not_stale_to_bedrock", + "ConfigKey": "max_unused_bedrock_access_days", + "Operator": "lte", + "Value": 60, + "Provider": "aws" + }, + { + "Check": "iam_role_access_not_stale_to_bedrock", + "ConfigKey": "max_unused_bedrock_access_days", + "Operator": "lte", + "Value": 60, + "Provider": "aws" + }, + { + "Check": "iam_user_access_not_stale_to_sagemaker", + "ConfigKey": "max_unused_sagemaker_access_days", + "Operator": "lte", + "Value": 90, + "Provider": "aws" + }, + { + "Check": "accessanalyzer_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-IAM-JIT", + "name": "Authorizing Just-in-Time", + "description": "A least-privileged, role and attribute-based, and just-in-time security authorization model is used and persistently reviewed for all user and non-user accounts and services.", + "attributes": { + "Theme": "KSI-IAM: Identity and Access Management", + "NISTControls": "AC-2, AC-2.1, AC-2.2, AC-2.3, AC-2.4, AC-2.6, AC-3, AC-4, AC-5, AC-6, AC-6.1, AC-6.2, AC-6.5, AC-6.7, AC-6.9, AC-6.10, AC-7, AC-20.1, AC-17, AU-9.4, CM-5, CM-7, CM-7.2, CM-7.5, CM-9, IA-4, IA-4.4, IA-7, PS-2, PS-3, PS-4, PS-5, PS-6, PS-9, RA-5.5, SC-2, SC-23, SC-39", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "bedrock_api_key_no_administrative_privileges", + "bedrock_full_access_policy_attached", + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges", + "iam_customer_unattached_policy_no_administrative_privileges", + "iam_group_administrator_access_policy", + "iam_inline_policy_allows_privilege_escalation", + "iam_inline_policy_no_administrative_privileges", + "iam_inline_policy_no_wildcard_marketplace_subscribe", + "iam_no_custom_policy_permissive_role_assumption", + "iam_policy_allows_privilege_escalation", + "iam_policy_attached_only_to_group_or_roles", + "iam_policy_cloudshell_admin_not_attached", + "iam_policy_no_agentcore_workload_access_token_wildcard", + "iam_policy_no_full_access_to_cloudtrail", + "iam_policy_no_full_access_to_kms", + "iam_policy_no_wildcard_marketplace_subscribe", + "iam_policy_passrole_to_bedrock_agentcore_restricted", + "iam_role_administratoraccess_policy", + "iam_role_cross_service_confused_deputy_prevention", + "iam_role_service_trust_restricts_source_to_account", + "iam_user_administrator_access_policy", + "iam_user_with_temporary_credentials", + "rolesanywhere_profile_restricts_session_permissions" + ], + "azure": [ + "app_function_identity_without_admin_privileges", + "entra_global_admin_in_less_than_five_users", + "iam_custom_role_has_permissions_to_administer_resource_locks", + "iam_role_user_access_admin_restricted", + "iam_subscription_roles_owner_custom_not_created", + "vm_jit_access_enabled" + ], + "gcp": [ + "iam_no_service_roles_at_project_level", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "iam_sa_no_administrative_privileges" + ], + "kubernetes": [], + "m365": [ + "entra_admin_users_sign_in_frequency_enabled", + "entra_intune_enrollment_sign_in_frequency_every_time", + "entra_pim_global_administrator_approval_required", + "entra_pim_privileged_role_administrator_approval_required", + "entra_service_principal_privileged_role_no_owners" + ] + } + }, + { + "id": "KSI-IAM-SNU", + "name": "Securing Non-User Authentication", + "description": "Appropriately secure authentication methods are used and persistently reviewed for non-user accounts and services.", + "attributes": { + "Theme": "KSI-IAM: Identity and Access Management", + "NISTControls": "AC-2, AC-2.2, AC-4, AC-6.5, IA-3, IA-5.2, RA-5.5", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "apigateway_restapi_authorizers_enabled", + "apigatewayv2_api_authorizers_enabled", + "appsync_graphql_api_no_api_key_authentication", + "bedrock_api_key_no_long_term_credentials", + "dms_endpoint_neptune_iam_authorization_enabled", + "ec2_instance_profile_attached", + "elasticache_redis_replication_group_auth_enabled", + "iam_rotate_access_key_90_days", + "iam_user_two_active_access_key", + "kafka_cluster_unrestricted_access_disabled", + "neptune_cluster_iam_authentication_enabled", + "rds_cluster_iam_authentication_enabled", + "rds_instance_iam_authentication_enabled" + ], + "azure": [ + "aks_cluster_local_accounts_disabled", + "app_function_identity_is_configured", + "app_register_with_identity", + "cosmosdb_account_use_aad_and_rbac", + "storage_account_key_access_disabled", + "storage_default_to_entra_authorization_enabled" + ], + "gcp": [ + "apikeys_api_restrictions_configured", + "apikeys_key_exists", + "apikeys_key_rotated_in_90_days", + "iam_sa_no_user_managed_keys", + "iam_sa_user_managed_key_rotate_90_days", + "iam_sa_user_managed_key_unused", + "iam_workload_identity_pool_provider_attribute_condition" + ], + "kubernetes": [ + "apiserver_kubelet_cert_auth", + "apiserver_kubelet_tls_auth", + "apiserver_no_token_auth_file", + "apiserver_service_account_key_file_set", + "apiserver_service_account_lookup_true", + "controllermanager_service_account_credentials", + "controllermanager_service_account_private_key_file", + "kubelet_client_ca_file_set" + ], + "m365": [ + "entra_app_registration_client_secret_unused", + "entra_default_app_management_policy_enabled", + "entra_service_principal_no_secrets_for_permanent_tier0_roles", + "exchange_shared_mailbox_sign_in_disabled" + ] + }, + "config_requirements": [ + { + "Check": "iam_sa_user_managed_key_unused", + "ConfigKey": "max_unused_account_days", + "Operator": "lte", + "Value": 180, + "Provider": "gcp" + } + ] + }, + { + "id": "KSI-IAM-SUS", + "name": "Responding to Suspicious Activity", + "description": "Accounts with privileged access are disabled or otherwise secured in response to suspicious activity.", + "attributes": { + "Theme": "KSI-IAM: Identity and Access Management", + "NISTControls": "AC-2, AC-2.1, AC-2.3, AC-2.13, AC-7, PS-4, PS-8", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "cognito_user_pool_advanced_security_enabled", + "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", + "cognito_user_pool_blocks_potential_malicious_sign_in_attempts" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [ + "entra_conditional_access_policy_block_elevated_insider_risk", + "entra_conditional_access_policy_block_high_medium_sign_in_risk", + "entra_conditional_access_policy_block_o365_elevated_insider_risk", + "entra_identity_protection_sign_in_risk_enabled", + "entra_identity_protection_user_risk_enabled", + "entra_password_protection_lockout_duration_configured", + "entra_password_protection_lockout_threshold_limited" + ] + }, + "config_requirements": [] + }, + { + "id": "KSI-INR-AAR", + "name": "Generating After Action Reports", + "description": "Incident after action reports are generated and lessons learned are persistently incorporated.", + "attributes": { + "Theme": "KSI-INR: Incident Response", + "NISTControls": "IR-3, IR-4, IR-4.1, IR-8", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-INR-RIR", + "name": "Reviewing Incident Response Procedures", + "description": "The effectiveness of documented incident response procedures is persistently reviewed.", + "attributes": { + "Theme": "KSI-INR: Incident Response", + "NISTControls": "IR-4, IR-4.1, IR-6, IR-6.1, IR-6.3, IR-7, IR-7.1, IR-8, IR-8.1, SI-4.5", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [] + }, + { + "id": "KSI-INR-RPI", + "name": "Reviewing Past Incidents", + "description": "Past incidents are persistently reviewed for patterns or vulnerabilities that were not previously apparent or identified.", + "attributes": { + "Theme": "KSI-INR: Incident Response", + "NISTControls": "IR-3, IR-4, IR-4.1, IR-5, IR-8", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-MLA-ALA", + "name": "Authorizing Log Access", + "description": "A least-privileged, role and attribute-based, and just-in-time access authorization model is used and persistently reviewed for access to log data based on organizationally defined data sensitivity.", + "attributes": { + "Theme": "KSI-MLA: Monitoring, Logging, and Auditing", + "NISTControls": "SI-11", + "ClassApplicability": "Optional for Class B, required for Class C" + }, + "checks": { + "aws": [ + "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", + "cloudwatch_cross_account_sharing_disabled", + "cloudwatch_log_group_not_publicly_accessible", + "iam_inline_policy_no_full_access_to_cloudtrail" + ], + "azure": [ + "monitor_storage_account_with_activity_logs_is_private" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-MLA-EVC", + "name": "Evaluating Configurations", + "description": "The configuration of machine-based information resources, especially infrastructure as code, is persistently evaluated and tested.", + "attributes": { + "Theme": "KSI-MLA: Monitoring, Logging, and Auditing", + "NISTControls": "CA-7, CM-2, CM-6, SI-7.7", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "config_recorder_all_regions_enabled" + ], + "azure": [ + "sqlserver_va_periodic_recurring_scans_enabled", + "sqlserver_vulnerability_assessment_enabled" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-MLA-LET", + "name": "Logging Event Types", + "description": "A list of information resources and event types that will be logged, monitored, and audited is maintained and persistently reviewed to ensure these activities occur.", + "attributes": { + "Theme": "KSI-MLA: Monitoring, Logging, and Auditing", + "NISTControls": "AC-2.4, AC-6.9, AC-17.1, AC-20.1, AU-2, AU-7.1, AU-12, SI-4.4, SI-4.5, SI-7.7", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "apigateway_restapi_logging_enabled", + "apigatewayv2_api_access_logging_enabled", + "appsync_field_level_logging_enabled", + "athena_workgroup_logging_enabled", + "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", + "bedrock_model_invocation_logging_enabled", + "cloudfront_distributions_logging_enabled", + "cloudtrail_bedrock_logging_enabled", + "cloudtrail_logs_s3_bucket_access_logging_enabled", + "cloudtrail_multi_region_enabled_logging_management_events", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "codebuild_project_logging_enabled", + "config_recorder_all_regions_enabled", + "datasync_task_logging_enabled", + "directoryservice_directory_log_forwarding_enabled", + "dms_replication_task_source_logging_enabled", + "dms_replication_task_target_logging_enabled", + "documentdb_cluster_cloudwatch_log_export", + "ec2_client_vpn_endpoint_connection_logging_enabled", + "ecs_cluster_container_insights_enabled", + "ecs_task_definitions_logging_enabled", + "eks_control_plane_logging_all_types_enabled", + "elasticbeanstalk_environment_cloudwatch_logging_enabled", + "elb_logging_enabled", + "elbv2_logging_enabled", + "glue_etl_jobs_logging_enabled", + "mq_broker_logging_enabled", + "neptune_cluster_integration_cloudwatch_logs", + "networkfirewall_logging_enabled", + "opensearch_service_domains_audit_logging_enabled", + "opensearch_service_domains_cloudwatch_logging_enabled", + "rds_cluster_integration_cloudwatch_logs", + "rds_instance_enhanced_monitoring_enabled", + "rds_instance_integration_cloudwatch_logs", + "redshift_cluster_audit_logging", + "route53_public_hosted_zones_cloudwatch_logging_enabled", + "s3_bucket_server_access_logging_enabled", + "stepfunctions_statemachine_logging_enabled", + "vpc_flow_logs_enabled", + "waf_global_webacl_logging_enabled", + "waf_regional_webacl_logging_enabled", + "wafv2_webacl_logging_enabled" + ], + "azure": [ + "aks_cluster_azure_monitor_enabled", + "app_function_application_insights_enabled", + "app_http_logs_enabled", + "appinsights_ensure_is_configured", + "defender_auto_provisioning_log_analytics_agent_vms_on", + "monitor_diagnostic_setting_with_appropriate_categories", + "monitor_diagnostic_settings_exists", + "mysql_flexible_server_audit_log_connection_activated", + "mysql_flexible_server_audit_log_enabled", + "network_flow_log_captured_sent", + "network_flow_log_more_than_90_days", + "network_watcher_enabled", + "postgresql_flexible_server_log_checkpoints_on", + "postgresql_flexible_server_log_connections_on", + "postgresql_flexible_server_log_disconnections_on", + "sqlserver_auditing_enabled", + "sqlserver_auditing_retention_90_days" + ], + "gcp": [ + "cloudsql_instance_postgres_enable_pgaudit_flag", + "cloudsql_instance_postgres_log_connections_flag", + "cloudsql_instance_postgres_log_disconnections_flag", + "cloudsql_instance_postgres_log_error_verbosity_flag", + "cloudsql_instance_postgres_log_min_duration_statement_flag", + "cloudsql_instance_postgres_log_min_error_statement_flag", + "cloudsql_instance_postgres_log_min_messages_flag", + "cloudsql_instance_postgres_log_statement_flag", + "cloudsql_instance_sqlserver_trace_flag", + "cloudstorage_audit_logs_enabled", + "cloudstorage_bucket_logging_enabled", + "compute_loadbalancer_logging_enabled", + "compute_network_dns_logging_enabled", + "compute_subnet_flow_logs_enabled", + "iam_audit_logs_enabled", + "logging_sink_created" + ], + "kubernetes": [ + "apiserver_audit_log_path_set" + ], + "m365": [ + "exchange_mailbox_audit_bypass_disabled", + "exchange_organization_mailbox_auditing_enabled", + "exchange_user_mailbox_auditing_enabled" + ] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + }, + { + "Check": "eks_control_plane_logging_all_types_enabled", + "ConfigKey": "eks_required_log_types", + "Operator": "superset", + "Value": [ + "api", + "audit", + "authenticator", + "controllerManager", + "scheduler" + ], + "Provider": "aws" + }, + { + "Check": "exchange_user_mailbox_auditing_enabled", + "ConfigKey": "audit_log_age", + "Operator": "gte", + "Value": 90, + "Provider": "m365" + } + ] + }, + { + "id": "KSI-MLA-OSM", + "name": "Operating SIEM Capability", + "description": "A Security Information and Event Management (SIEM) or similar system(s) is used and persistently reviewed for centralized, tamper-resistant logging of events, activities, and changes.", + "attributes": { + "Theme": "KSI-MLA: Monitoring, Logging, and Auditing", + "NISTControls": "AC-17.1, AC-20.1, AU-2, AU-3, AU-3.1, AU-4, AU-5, AU-6.1, AU-6.3, AU-7, AU-7.1, AU-8, AU-9, AU-11, IR-4.1, SI-4.2, SI-4.4, SI-7.7", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "cloudtrail_bucket_requires_mfa_delete", + "cloudtrail_cloudwatch_logging_enabled", + "cloudtrail_kms_encryption_enabled", + "cloudtrail_log_file_validation_enabled", + "cloudtrail_multi_region_enabled", + "cloudwatch_log_group_kms_encryption_enabled", + "cloudwatch_log_group_retention_policy_specific_days_enabled" + ], + "azure": [ + "monitor_diagnostic_settings_exists" + ], + "gcp": [ + "cloudstorage_bucket_log_retention_policy_lock", + "iam_audit_logs_enabled", + "logging_sink_created" + ], + "kubernetes": [ + "apiserver_audit_log_maxage_set", + "apiserver_audit_log_maxbackup_set", + "apiserver_audit_log_maxsize_set", + "apiserver_audit_log_path_set" + ], + "m365": [ + "purview_audit_log_search_enabled" + ] + }, + "config_requirements": [ + { + "Check": "apiserver_audit_log_maxage_set", + "ConfigKey": "audit_log_maxage", + "Operator": "gte", + "Value": 30, + "Provider": "kubernetes" + }, + { + "Check": "apiserver_audit_log_maxbackup_set", + "ConfigKey": "audit_log_maxbackup", + "Operator": "gte", + "Value": 10, + "Provider": "kubernetes" + }, + { + "Check": "apiserver_audit_log_maxsize_set", + "ConfigKey": "audit_log_maxsize", + "Operator": "gte", + "Value": 100, + "Provider": "kubernetes" + }, + { + "Check": "cloudwatch_log_group_retention_policy_specific_days_enabled", + "ConfigKey": "log_group_retention_days", + "Operator": "gte", + "Value": 365, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-MLA-RVL", + "name": "Reviewing Logs", + "description": "Logs are persistently reviewed and audited.", + "attributes": { + "Theme": "KSI-MLA: Monitoring, Logging, and Auditing", + "NISTControls": "AC-2.4, AC-6.9, AU-2, AU-6, AU-6.1, SI-4, SI-4.4", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-PIY-GIV", + "name": "Generating Inventories", + "description": "Authoritative sources are used to automatically generate real-time inventories of all information resources when needed.", + "attributes": { + "Theme": "KSI-PIY: Policy and Inventory", + "NISTControls": "CM-2.2, CM-7.5, CM-8, CM-8.1, CM-12, CM-12.1, CP-2.8", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "config_delegated_admin_and_org_aggregator_all_regions", + "config_recorder_all_regions_enabled", + "resourceexplorer2_indexes_found" + ], + "azure": [], + "gcp": [ + "iam_cloud_asset_inventory_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + }, + { + "Check": "config_delegated_admin_and_org_aggregator_all_regions", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-PIY-RES", + "name": "Reviewing Executive Support", + "description": "Executive support for achieving the provider's security goals is persistently reviewed and demonstrated.", + "attributes": { + "Theme": "KSI-PIY: Policy and Inventory", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-PIY-RIS", + "name": "Reviewing Investments in Security", + "description": "The effectiveness of the provider's investments in achieving security goals is persistently reviewed.", + "attributes": { + "Theme": "KSI-PIY: Policy and Inventory", + "NISTControls": "AC-5, CA-2, CP-2.1, CP-4.1, IR-3.2, PM-3, SA-2, SA-3, SR-2.1", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-PIY-RSD", + "name": "Reviewing Security in the SDLC", + "description": "The effectiveness of building security and privacy considerations into the Software Development Lifecycle and aligning with CISA Secure By Design principles is persistently reviewed.", + "attributes": { + "Theme": "KSI-PIY: Policy and Inventory", + "NISTControls": "AC-5, AU-3.3, CM-3.4, PL-8, PM-7, SA-3, SA-8, SC-4, SC-18, SI-10, SI-11, SI-16", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-PIY-RVD", + "name": "Reviewing Vulnerability Disclosures", + "description": "The effectiveness of the provider's vulnerability disclosure program is persistently reviewed.", + "attributes": { + "Theme": "KSI-PIY: Policy and Inventory", + "NISTControls": "RA-5.11", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-RPL-ABO", + "name": "Aligning Backups with Objectives", + "description": "The alignment of machine-based information resource backups with defined recovery objectives is persistently reviewed.", + "attributes": { + "Theme": "KSI-RPL: Recovery Planning", + "NISTControls": "CM-2.3, CP-6, CP-9, CP-10, CP-10.2, SI-12", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "dlm_ebs_snapshot_lifecycle_policy_exists", + "documentdb_cluster_backup_enabled", + "dynamodb_table_protected_by_backup_plan", + "dynamodb_tables_pitr_enabled", + "ec2_ebs_volume_protected_by_backup_plan", + "ec2_ebs_volume_snapshots_exists", + "efs_have_backup_enabled", + "elasticache_redis_cluster_backup_enabled", + "lightsail_instance_automated_snapshots", + "neptune_cluster_backup_enabled", + "rds_cluster_backtrack_enabled", + "rds_cluster_protected_by_backup_plan", + "rds_instance_backup_enabled", + "rds_instance_protected_by_backup_plan", + "redshift_cluster_automated_snapshot", + "s3_bucket_cross_region_replication", + "s3_bucket_object_versioning" + ], + "azure": [ + "cosmosdb_account_backup_policy_continuous", + "keyvault_recoverable", + "mysql_flexible_server_geo_redundant_backup_enabled", + "postgresql_flexible_server_geo_redundant_backup_enabled", + "recovery_vault_backup_policy_retention_adequate", + "recovery_vault_has_protected_items", + "storage_blob_versioning_is_enabled", + "storage_ensure_file_shares_soft_delete_is_enabled", + "storage_ensure_soft_delete_is_enabled", + "storage_geo_redundant_enabled", + "vm_backup_enabled", + "vm_sufficient_daily_backup_retention_period" + ], + "gcp": [ + "cloudsql_instance_automated_backups", + "cloudstorage_bucket_soft_delete_enabled", + "cloudstorage_bucket_sufficient_retention_period", + "cloudstorage_bucket_versioning_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "vm_sufficient_daily_backup_retention_period", + "ConfigKey": "vm_backup_min_daily_retention_days", + "Operator": "gte", + "Value": 7, + "Provider": "azure" + }, + { + "Check": "documentdb_cluster_backup_enabled", + "ConfigKey": "minimum_backup_retention_period", + "Operator": "gte", + "Value": 7, + "Provider": "aws" + }, + { + "Check": "neptune_cluster_backup_enabled", + "ConfigKey": "minimum_backup_retention_period", + "Operator": "gte", + "Value": 7, + "Provider": "aws" + }, + { + "Check": "elasticache_redis_cluster_backup_enabled", + "ConfigKey": "minimum_snapshot_retention_period", + "Operator": "gte", + "Value": 7, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-RPL-ARP", + "name": "Aligning Recovery Plan", + "description": "The alignment of recovery plans with defined recovery objectives is persistently reviewed.", + "attributes": { + "Theme": "KSI-RPL: Recovery Planning", + "NISTControls": "CP-2, CP-2.1, CP-2.3, CP-4.1, CP-6, CP-6.1, CP-6.3, CP-7, CP-7.1, CP-7.2, CP-7.3, CP-8, CP-8.1, CP-8.2, CP-10, CP-10.2", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "backup_plans_exist", + "backup_reportplans_exist", + "backup_vaults_exist" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [] + }, + { + "id": "KSI-RPL-RRO", + "name": "Reviewing Recovery Objectives", + "description": "The desired Recovery Time Objectives (RTO) and Recovery Point Objectives (RPO) are defined and persistently reviewed for alignment with the provider's business needs and capabilities.", + "attributes": { + "Theme": "KSI-RPL: Recovery Planning", + "NISTControls": "CP-2.3, CP-10", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-RPL-TRC", + "name": "Testing Recovery Capabilities", + "description": "The capability to recover from incidents and contingencies aligned with defined recovery objectives is persistently tested.", + "attributes": { + "Theme": "KSI-RPL: Recovery Planning", + "NISTControls": "CP-2.1, CP-2.3, CP-4, CP-4.1, CP-6, CP-6.1, CP-9.1, CP-10, IR-3, IR-3.2", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "drs_job_exist" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "drs_job_exist", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-SCR-MIT", + "name": "Mitigating Supply Chain Risk", + "description": "Persistently identify, review, and mitigate potential supply chain risks.", + "attributes": { + "Theme": "KSI-SCR: Supply Chain Risk", + "NISTControls": "AC-20, RA-3.1, SA-9, SA-10, SA-11, SA-15.3, SA-22, SI-7.1, SR-5, SR-6, CA-7.4, SC-18", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "awslambda_function_using_cross_account_layers", + "codeartifact_packages_external_public_publishing_disabled", + "codebuild_project_user_controlled_buildspec", + "codebuild_project_uses_allowed_github_organizations", + "ecr_registry_enhanced_scanning_enabled", + "ecr_registry_scan_images_on_push_enabled", + "ecr_repositories_not_publicly_accessible", + "ecr_repositories_scan_vulnerabilities_in_latest_image", + "ecr_repositories_tag_immutability", + "s3_bucket_shadow_resource_vulnerability" + ], + "azure": [ + "defender_container_images_resolved_vulnerabilities", + "defender_container_images_scan_enabled" + ], + "gcp": [ + "artifacts_container_analysis_enabled", + "gcr_container_scanning_enabled" + ], + "kubernetes": [ + "apiserver_always_pull_images_plugin" + ], + "m365": [] + }, + "config_requirements": [ + { + "Check": "ecr_repositories_scan_vulnerabilities_in_latest_image", + "ConfigKey": "ecr_repository_vulnerability_minimum_severity", + "Operator": "in", + "Value": [ + "MEDIUM" + ], + "Provider": "aws" + } + ] + }, + { + "id": "KSI-SCR-MON", + "name": "Monitoring Supply Chain Risk", + "description": "Third party software information resources are automatically monitored for upstream vulnerabilities using mechanisms that may include contractual notification requirements or active monitoring services.", + "attributes": { + "Theme": "KSI-SCR: Supply Chain Risk", + "NISTControls": "AC-20, CA-3, IR-6.3, PS-7, RA-5, SA-9, SI-5, SR-5, SR-6, SR-8", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "awslambda_function_using_supported_runtimes", + "ecr_registry_enhanced_scanning_enabled", + "inspector2_active_findings_exist", + "inspector2_is_enabled", + "ssm_managed_compliant_patching" + ], + "azure": [ + "app_ensure_java_version_is_latest", + "app_ensure_php_version_is_latest", + "app_ensure_python_version_is_latest", + "app_function_latest_runtime_version", + "defender_ensure_system_updates_are_applied" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "awslambda_function_using_supported_runtimes", + "ConfigKey": "obsolete_lambda_runtimes", + "Operator": "superset", + "Value": [ + "java8", + "go1.x", + "provided", + "python3.6", + "python2.7", + "python3.7", + "python3.8", + "nodejs4.3", + "nodejs4.3-edge", + "nodejs6.10", + "nodejs", + "nodejs8.10", + "nodejs10.x", + "nodejs12.x", + "nodejs14.x", + "nodejs16.x", + "dotnet5.0", + "dotnet6", + "dotnet7", + "dotnetcore1.0", + "dotnetcore2.0", + "dotnetcore2.1", + "dotnetcore3.1", + "ruby2.5", + "ruby2.7" + ], + "Provider": "aws" + } + ] + }, + { + "id": "KSI-SVC-ACM", + "name": "Automating Configuration Management", + "description": "The configuration of machine-based information resources is managed using automation and persistently reviewed for drift.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "AC-2.4, CM-2, CM-2.2, CM-2.3, CM-6, CM-7.1, PL-9, PL-10, SA-5, SI-5, SR-10", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "config_recorder_all_regions_enabled", + "ec2_instance_managed_by_ssm", + "ssm_managed_compliant_patching" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-SVC-ASM", + "name": "Automating Secret Management", + "description": "Management, protection, and regular rotation of digital keys, certificates, and other secrets is automated and persistently reviewed.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "AC-17.2, IA-5.2, IA-5.6, SC-12, SC-17", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "acm_certificates_expiration_check", + "amplify_app_no_secrets_in_environment", + "apigateway_restapi_no_secrets_in_stage_variables", + "awslambda_function_no_secrets_in_code", + "awslambda_function_no_secrets_in_variables", + "awslambda_layer_no_secrets_in_content", + "batch_job_definition_no_secrets", + "cloudformation_stack_outputs_find_secrets", + "cloudwatch_log_group_no_secrets_in_logs", + "codebuild_project_no_secrets_in_variables", + "codebuild_project_source_repo_url_no_sensitive_credentials", + "codecommit_repository_no_secrets", + "datapipeline_pipeline_no_secrets_in_definition", + "directoryservice_ldap_certificate_expiration", + "ec2_instance_secrets_user_data", + "ec2_launch_template_no_secrets", + "ecr_repository_image_no_secrets", + "ecs_task_definitions_no_environment_secrets", + "elasticbeanstalk_environment_no_secrets_in_configuration", + "glue_catalog_connection_no_secrets", + "glue_etl_jobs_no_secrets_in_arguments", + "iam_no_expired_server_certificates_stored", + "kms_cmk_rotation_enabled", + "kms_key_not_publicly_accessible", + "rds_instance_certificate_expiration", + "sagemaker_notebook_instance_no_secrets", + "secretsmanager_automatic_rotation_enabled", + "secretsmanager_has_restrictive_resource_policy", + "secretsmanager_not_publicly_accessible", + "secretsmanager_secret_rotated_periodically", + "secretsmanager_secret_unused", + "ssm_document_secrets", + "stepfunctions_statemachine_no_secrets_in_definition" + ], + "azure": [ + "entra_app_registration_credential_not_expired", + "keyvault_key_expiration_set_in_non_rbac", + "keyvault_key_rotation_enabled", + "keyvault_non_rbac_secret_expiration_set", + "keyvault_rbac_key_expiration_set", + "keyvault_rbac_secret_expiration_set", + "storage_key_rotation_90_days" + ], + "gcp": [ + "kms_key_not_publicly_accessible", + "kms_key_rotation_enabled", + "kms_key_rotation_max_90_days", + "secretmanager_secret_not_publicly_accessible", + "secretmanager_secret_rotation_enabled" + ], + "kubernetes": [ + "apiserver_encryption_provider_config_set", + "apiserver_service_account_key_file_set", + "controllermanager_rotate_kubelet_server_cert", + "controllermanager_service_account_private_key_file", + "kubelet_rotate_certificates" + ], + "m365": [ + "entra_policy_default_user_cannot_read_bitlocker_keys" + ] + }, + "config_requirements": [ + { + "Check": "acm_certificates_expiration_check", + "ConfigKey": "days_to_expire_threshold", + "Operator": "gte", + "Value": 7, + "Provider": "aws" + }, + { + "Check": "secretsmanager_secret_unused", + "ConfigKey": "max_days_secret_unused", + "Operator": "lte", + "Value": 90, + "Provider": "aws" + }, + { + "Check": "secretsmanager_secret_rotated_periodically", + "ConfigKey": "max_days_secret_unrotated", + "Operator": "lte", + "Value": 90, + "Provider": "aws" + } + ] + }, + { + "id": "KSI-SVC-EIS", + "name": "Evaluating and Improving Security", + "description": "Information resources are persistently evaluated for opportunities to improve security and those improvements are persistently made.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "CM-7.1, CM-12.1, MA-2, PL-8, SC-7, SC-39, SI-2.2, SI-4, SR-10", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "trustedadvisor_errors_and_warnings" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [] + }, + { + "id": "KSI-SVC-PRR", + "name": "Preventing Residual Risk", + "description": "Plans, procedures, and the state of information resources are persistently reviewed after making changes to limit and remove unwanted residual elements that would likely negatively affect the confidentiality, integrity, or availability of federal customer data.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "SC-4", + "ClassApplicability": "Optional for Class B, required for Class C" + }, + "checks": { + "aws": [ + "cloudfront_distributions_s3_origin_non_existent_bucket", + "ec2_elastic_ip_unassigned", + "lightsail_static_ip_unused", + "route53_dangling_ip_subdomain_takeover" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-SVC-RUD", + "name": "Removing Unwanted Data", + "description": "Unwanted federal customer data is removed promptly when requested by an agency in alignment with customer agreements, including from backups if appropriate; this typically applies when a customer spills information or when a customer seeks to remove information from a service due to a change in usage.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "SI-12.3, SI-18.4", + "ClassApplicability": "Optional for Class B, required for Class C" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "KSI-SVC-SIN", + "name": "Securing Information", + "description": "Information is encrypted or otherwise secured from unwanted access or modification.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "AC-1, AC-17.2, CP-9.8, SC-8, SC-8.1, SC-13, SC-20, SC-21, SC-22, SC-23, SC-28, SC-28.1", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "apigateway_restapi_cache_encrypted", + "athena_workgroup_encryption", + "awslambda_function_env_vars_not_encrypted_with_cmk", + "backup_recovery_point_encrypted", + "backup_vaults_encrypted", + "bedrock_custom_model_encrypted_with_cmk", + "bedrock_knowledge_base_encrypted_with_cmk", + "bedrock_prompt_encrypted_with_cmk", + "cloudfront_distributions_field_level_encryption_enabled", + "cloudfront_distributions_https_enabled", + "cloudfront_distributions_origin_traffic_encrypted", + "cloudfront_distributions_s3_origin_access_control", + "cloudfront_distributions_using_deprecated_ssl_protocols", + "codebuild_report_group_export_encrypted", + "dms_endpoint_redis_in_transit_encryption_enabled", + "dms_endpoint_ssl_enabled", + "documentdb_cluster_public_snapshot", + "documentdb_cluster_storage_encrypted", + "dynamodb_accelerator_cluster_encryption_enabled", + "dynamodb_accelerator_cluster_in_transit_encryption_enabled", + "dynamodb_table_cross_account_access", + "dynamodb_tables_kms_cmk_encryption_enabled", + "ec2_ami_account_block_public_access", + "ec2_ami_public", + "ec2_ebs_default_encryption", + "ec2_ebs_public_snapshot", + "ec2_ebs_snapshot_account_block_public_access", + "ec2_ebs_snapshots_encrypted", + "ec2_ebs_volume_encryption", + "efs_encryption_at_rest_enabled", + "efs_not_publicly_accessible", + "eks_cluster_kms_cmk_encryption_in_secrets_enabled", + "elasticache_redis_cluster_in_transit_encryption_enabled", + "elasticache_redis_cluster_rest_encryption_enabled", + "elb_insecure_ssl_ciphers", + "elb_ssl_listeners", + "elbv2_insecure_ssl_ciphers", + "elbv2_nlb_tls_termination_enabled", + "elbv2_ssl_listeners", + "eventbridge_bus_cross_account_access", + "eventbridge_bus_exposed", + "firehose_stream_encrypted_at_rest", + "glacier_vaults_policy_public_access", + "glue_data_catalogs_metadata_encryption_enabled", + "glue_data_catalogs_not_publicly_accessible", + "glue_database_connections_ssl_enabled", + "glue_development_endpoints_job_bookmark_encryption_enabled", + "glue_development_endpoints_s3_encryption_enabled", + "glue_etl_jobs_amazon_s3_encryption_enabled", + "glue_etl_jobs_job_bookmark_encryption_enabled", + "glue_ml_transform_encrypted_at_rest", + "kafka_cluster_encryption_at_rest_uses_cmk", + "kafka_cluster_in_transit_encryption_enabled", + "kafka_connector_in_transit_encryption_enabled", + "kinesis_stream_encrypted_at_rest", + "memorydb_cluster_in_transit_encryption_enabled", + "neptune_cluster_public_snapshot", + "neptune_cluster_snapshot_encrypted", + "neptune_cluster_storage_encrypted", + "opensearch_service_domains_encryption_at_rest_enabled", + "opensearch_service_domains_https_communications_enforced", + "opensearch_service_domains_node_to_node_encryption_enabled", + "rds_cluster_storage_encrypted", + "rds_instance_storage_encrypted", + "rds_instance_transport_encrypted", + "rds_snapshots_encrypted", + "rds_snapshots_public_access", + "redshift_cluster_encrypted_at_rest", + "redshift_cluster_in_transit_encryption_enabled", + "s3_access_point_public_access_block", + "s3_account_level_public_access_blocks", + "s3_bucket_acl_prohibited", + "s3_bucket_cross_account_access", + "s3_bucket_kms_encryption", + "s3_bucket_level_public_access_block", + "s3_bucket_no_mfa_delete", + "s3_bucket_object_lock", + "s3_bucket_object_public", + "s3_bucket_policy_public_write_access", + "s3_bucket_public_access", + "s3_bucket_public_list_acl", + "s3_bucket_public_write_acl", + "s3_bucket_secure_transport_policy", + "s3_multi_region_access_point_public_access_block", + "sagemaker_endpoint_config_kms_encryption_enabled", + "sagemaker_notebook_instance_encryption_enabled", + "sagemaker_training_jobs_intercontainer_encryption_enabled", + "sagemaker_training_jobs_volume_and_output_encryption_enabled", + "sns_subscription_not_using_http_endpoints", + "sns_topics_not_publicly_accessible", + "sqs_queues_not_publicly_accessible", + "sqs_queues_server_side_encryption_enabled", + "ssm_documents_set_as_public", + "stepfunctions_statemachine_encrypted_with_cmk", + "storagegateway_fileshare_encryption_enabled", + "transfer_server_in_transit_encryption_enabled", + "workspaces_volume_encryption_enabled" + ], + "azure": [ + "app_client_certificates_on", + "app_ensure_auth_is_set_up", + "app_ensure_http_is_redirected_to_https", + "app_ftp_deployment_disabled", + "app_function_ensure_http_is_redirected_to_https", + "app_minimum_tls_version_12", + "cosmosdb_account_minimum_tls_version", + "databricks_workspace_cmk_encryption_enabled", + "monitor_storage_account_with_activity_logs_cmk_encrypted", + "mysql_flexible_server_minimum_tls_version_12", + "mysql_flexible_server_ssl_connection_enabled", + "postgresql_flexible_server_enforce_ssl_enabled", + "sqlserver_recommended_minimal_tls_version", + "sqlserver_tde_encrypted_with_cmk", + "sqlserver_tde_encryption_enabled", + "storage_blob_public_access_level_is_disabled", + "storage_ensure_encryption_with_customer_managed_keys", + "storage_ensure_minimum_tls_version_12", + "storage_infrastructure_encryption_is_enabled", + "storage_secure_transfer_required_is_enabled", + "storage_smb_channel_encryption_with_secure_algorithm", + "vm_ensure_attached_disks_encrypted_with_cmk", + "vm_ensure_unattached_disks_encrypted_with_cmk" + ], + "gcp": [ + "bigquery_dataset_cmk_encryption", + "bigquery_dataset_public_access", + "bigquery_table_cmk_encryption", + "cloudsql_instance_cmek_encryption_enabled", + "cloudsql_instance_ssl_connections", + "cloudstorage_bucket_public_access", + "compute_image_not_publicly_shared", + "compute_instance_confidential_computing_enabled", + "compute_instance_encryption_with_csek_enabled", + "dataproc_encrypted_with_cmks_disabled" + ], + "kubernetes": [ + "apiserver_encryption_provider_config_set", + "apiserver_etcd_tls_config", + "apiserver_tls_config", + "etcd_peer_tls_config", + "etcd_tls_encryption", + "kubelet_tls_cert_and_key", + "rbac_minimize_secret_access" + ], + "m365": [ + "exchange_organization_modern_authentication_enabled", + "exchange_transport_config_smtp_auth_disabled", + "sharepoint_modern_authentication_required" + ] + }, + "config_requirements": [ + { + "Check": "sqlserver_recommended_minimal_tls_version", + "ConfigKey": "recommended_minimal_tls_versions", + "Operator": "subset", + "Value": [ + "1.2", + "1.3" + ], + "Provider": "azure" + }, + { + "Check": "storage_smb_channel_encryption_with_secure_algorithm", + "ConfigKey": "recommended_smb_channel_encryption_algorithms", + "Operator": "subset", + "Value": [ + "AES-256-GCM" + ], + "Provider": "azure" + } + ] + }, + { + "id": "KSI-SVC-VCM", + "name": "Validating Communications", + "description": "The authenticity and integrity of communications between machine-based information resources is persistently validated using automation.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "SC-23, SI-7.1", + "ClassApplicability": "Optional for Class B, required for Class C" + }, + "checks": { + "aws": [ + "apigateway_restapi_client_certificate_enabled", + "kafka_cluster_mutual_tls_authentication_enabled", + "ses_identity_dkim_enabled" + ], + "azure": [ + "app_client_certificates_on" + ], + "gcp": [ + "dns_dnssec_disabled" + ], + "kubernetes": [ + "apiserver_client_ca_file_set", + "apiserver_etcd_tls_config", + "apiserver_kubelet_cert_auth", + "apiserver_kubelet_tls_auth", + "etcd_client_cert_auth", + "etcd_no_auto_tls", + "etcd_no_peer_auto_tls", + "etcd_peer_client_cert_auth", + "etcd_peer_tls_config", + "kubelet_client_ca_file_set" + ], + "m365": [ + "defender_domain_dkim_enabled", + "defender_domain_dmarc_records_published", + "exchange_organization_reject_direct_send_enabled" + ] + } + }, + { + "id": "KSI-SVC-VRI", + "name": "Validating Resource Integrity", + "description": "Use cryptographic methods to validate the integrity of machine-based information resources.", + "attributes": { + "Theme": "KSI-SVC: Service Configuration", + "NISTControls": "CM-2.2, CM-8.3, SC-13, SC-23, SI-7, SI-7.1, SR-10", + "ClassApplicability": "Required for Classes B and C" + }, + "checks": { + "aws": [ + "cloudtrail_log_file_validation_enabled", + "kms_key_enclave_attestation_bypassable_path", + "kms_key_enclave_attestation_no_deployment_binding", + "kms_key_enclave_attestation_not_enforced", + "kms_key_enclave_attestation_pcr_mismatch", + "kms_key_enclave_attestation_unknown_image", + "kms_key_enclave_debug_attestation_detected" + ], + "azure": [ + "vm_trusted_launch_enabled" + ], + "gcp": [ + "compute_instance_shielded_vm_enabled", + "dns_dnssec_disabled", + "dns_rsasha1_in_use_to_key_sign_in_dnssec", + "dns_rsasha1_in_use_to_zone_sign_in_dnssec" + ], + "kubernetes": [ + "apiserver_etcd_cafile_set", + "controllermanager_root_ca_file_set", + "etcd_client_cert_auth", + "etcd_peer_client_cert_auth" + ], + "m365": [] + }, + "config_requirements": [ + { + "Check": "kms_key_enclave_debug_attestation_detected", + "ConfigKey": "enclave_debug_lookback_window_hours", + "Operator": "gte", + "Value": 2160, + "Provider": "aws" + }, + { + "Check": "kms_key_enclave_debug_attestation_detected", + "ConfigKey": "enclave_debug_max_events", + "Operator": "gte", + "Value": 5000, + "Provider": "aws" + }, + { + "Check": "kms_key_enclave_attestation_unknown_image", + "ConfigKey": "enclave_unknown_image_lookback_window_hours", + "Operator": "gte", + "Value": 2160, + "Provider": "aws" + }, + { + "Check": "kms_key_enclave_attestation_unknown_image", + "ConfigKey": "enclave_unknown_image_max_events", + "Operator": "gte", + "Value": 5000, + "Provider": "aws" + } + ] + } + ] +} diff --git a/prowler/compliance/gcp/fedramp_20x_ksi_low_gcp.json b/prowler/compliance/gcp/fedramp_20x_ksi_low_gcp.json deleted file mode 100644 index 5638b0c51e..0000000000 --- a/prowler/compliance/gcp/fedramp_20x_ksi_low_gcp.json +++ /dev/null @@ -1,294 +0,0 @@ -{ - "Framework": "FedRAMP-20x-KSI-Low", - "Name": "FedRAMP 20x Key Security Indicators (KSIs) - Low Impact Level v25.05C", - "Version": "25.05C", - "Provider": "GCP", - "Description": "FedRAMP 20x Key Security Indicators (KSIs) Low Impact Level represent core security indicators for cloud service providers, focusing on automation, continuous monitoring, and cloud-native security principles per FedRAMP 20x Phase One pilot requirements for Low impact systems.", - "Requirements": [ - { - "Id": "ksi-cmt", - "Name": "KSI-CMT: Change Management", - "Description": "A secure cloud service provider will ensure that all system changes are properly documented and configuration baselines are updated accordingly", - "Attributes": [ - { - "ItemId": "ksi-cmt", - "Section": "Change Management", - "Service": "gcp" - } - ], - "Checks": [ - "iam_audit_logs_enabled", - "iam_cloud_asset_inventory_enabled", - "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", - "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", - "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", - "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", - "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", - "compute_instance_serial_ports_in_use", - "compute_project_os_login_enabled" - ] - }, - { - "Id": "ksi-cna", - "Name": "KSI-CNA: Cloud Native Architecture", - "Description": "A secure cloud service offering will use cloud native architecture and design principles to enforce and enhance the Confidentiality, Integrity and Availability of the system", - "Attributes": [ - { - "ItemId": "ksi-cna", - "Section": "Cloud Native Architecture", - "Service": "gcp" - } - ], - "Checks": [ - "cloudsql_instance_private_ip_assignment", - "cloudsql_instance_public_access", - "cloudsql_instance_public_ip", - "cloudstorage_bucket_uniform_bucket_level_access", - "compute_firewall_rdp_access_from_the_internet_allowed", - "compute_firewall_ssh_access_from_the_internet_allowed", - "compute_instance_block_project_wide_ssh_keys_disabled", - "compute_instance_confidential_computing_enabled", - "compute_instance_ip_forwarding_is_enabled", - "compute_instance_public_ip", - "compute_instance_shielded_vm_enabled", - "compute_loadbalancer_logging_enabled", - "compute_network_default_in_use", - "compute_network_dns_logging_enabled", - "compute_network_not_legacy", - "compute_subnet_flow_logs_enabled", - "gke_cluster_no_default_service_account" - ] - }, - { - "Id": "ksi-iam", - "Name": "KSI-IAM: Identity and Access Management", - "Description": "A secure cloud service offering will protect user data, control access, and apply zero trust principles", - "Attributes": [ - { - "ItemId": "ksi-iam", - "Section": "Identity and Access Management", - "Service": "gcp" - } - ], - "Checks": [ - "apikeys_api_restrictions_configured", - "apikeys_key_exists", - "apikeys_key_rotated_in_90_days", - "compute_instance_default_service_account_in_use", - "compute_instance_default_service_account_in_use_with_full_api_access", - "iam_no_service_roles_at_project_level", - "iam_role_kms_enforce_separation_of_duties", - "iam_role_sa_enforce_separation_of_duties", - "iam_sa_no_administrative_privileges", - "iam_sa_no_user_managed_keys", - "iam_sa_user_managed_key_rotate_90_days", - "iam_sa_user_managed_key_unused", - "iam_service_account_unused" - ] - }, - { - "Id": "ksi-inr", - "Name": "KSI-INR: Incident Response", - "Description": "A secure cloud service offering will respond to incidents according to FedRAMP requirements and cloud service provider policies", - "Attributes": [ - { - "ItemId": "ksi-inr", - "Section": "Incident Response", - "Service": "gcp" - } - ], - "Checks": [ - "iam_organization_essential_contacts_configured", - "iam_account_access_approval_enabled", - "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", - "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", - "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", - "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", - "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled" - ] - }, - { - "Id": "ksi-mla", - "Name": "KSI-MLA: Monitoring, Logging, and Auditing", - "Description": "A secure cloud service offering will monitor, log, and audit all important events, activity, and changes", - "Attributes": [ - { - "ItemId": "ksi-mla", - "Section": "Monitoring, Logging, and Auditing", - "Service": "gcp" - } - ], - "Checks": [ - "cloudsql_instance_postgres_enable_pgaudit_flag", - "cloudsql_instance_postgres_log_connections_flag", - "cloudsql_instance_postgres_log_disconnections_flag", - "cloudsql_instance_postgres_log_error_verbosity_flag", - "cloudsql_instance_postgres_log_min_duration_statement_flag", - "cloudsql_instance_postgres_log_min_error_statement_flag", - "cloudsql_instance_postgres_log_min_messages_flag", - "cloudsql_instance_postgres_log_statement_flag", - "cloudsql_instance_sqlserver_trace_flag", - "cloudstorage_bucket_log_retention_policy_lock", - "compute_loadbalancer_logging_enabled", - "compute_network_dns_logging_enabled", - "compute_subnet_flow_logs_enabled", - "iam_audit_logs_enabled", - "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", - "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", - "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", - "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", - "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", - "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", - "logging_sink_created" - ] - }, - { - "Id": "ksi-piy", - "Name": "KSI-PIY: Policy and Inventory", - "Description": "A secure cloud service offering will have intentional, organized, universal guidance for how every information resource, including personnel, is secured", - "Attributes": [ - { - "ItemId": "ksi-piy", - "Section": "Policy and Inventory", - "Service": "gcp" - } - ], - "Checks": [ - "iam_cloud_asset_inventory_enabled", - "iam_organization_essential_contacts_configured", - "iam_audit_logs_enabled", - "compute_project_os_login_enabled", - "compute_instance_serial_ports_in_use", - "compute_instance_block_project_wide_ssh_keys_disabled", - "logging_sink_created" - ] - }, - { - "Id": "ksi-rpl", - "Name": "KSI-RPL: Recovery Planning", - "Description": "A secure cloud service offering will define, maintain, and test incident response plan(s) and recovery capabilities to ensure minimal service disruption and data loss", - "Attributes": [ - { - "ItemId": "ksi-rpl", - "Section": "Recovery Planning", - "Service": "gcp" - } - ], - "Checks": [ - "cloudsql_instance_automated_backups", - "cloudstorage_bucket_log_retention_policy_lock", - "cloudstorage_bucket_versioning_enabled", - "cloudstorage_bucket_lifecycle_management_enabled" - ] - }, - { - "Id": "ksi-svc", - "Name": "KSI-SVC: Service Configuration", - "Description": "A secure cloud service offering will follow FedRAMP encryption policies, continuously verify information resource integrity, and restrict access to third-party information resources", - "Attributes": [ - { - "ItemId": "ksi-svc", - "Section": "Service Configuration", - "Service": "gcp" - } - ], - "Checks": [ - "bigquery_dataset_cmk_encryption", - "bigquery_table_cmk_encryption", - "cloudsql_instance_mysql_local_infile_flag", - "cloudsql_instance_mysql_skip_show_database_flag", - "cloudsql_instance_postgres_enable_pgaudit_flag", - "cloudsql_instance_postgres_log_connections_flag", - "cloudsql_instance_postgres_log_disconnections_flag", - "cloudsql_instance_postgres_log_error_verbosity_flag", - "cloudsql_instance_postgres_log_min_duration_statement_flag", - "cloudsql_instance_postgres_log_min_error_statement_flag", - "cloudsql_instance_postgres_log_min_messages_flag", - "cloudsql_instance_postgres_log_statement_flag", - "cloudsql_instance_sqlserver_contained_database_authentication_flag", - "cloudsql_instance_sqlserver_cross_db_ownership_chaining_flag", - "cloudsql_instance_sqlserver_external_scripts_enabled_flag", - "cloudsql_instance_sqlserver_remote_access_flag", - "cloudsql_instance_sqlserver_trace_flag", - "cloudsql_instance_sqlserver_user_connections_flag", - "cloudsql_instance_sqlserver_user_options_flag", - "cloudsql_instance_ssl_connections", - "compute_instance_encryption_with_csek_enabled", - "compute_instance_shielded_vm_enabled", - "dataproc_encrypted_with_cmks_disabled", - "dns_dnssec_disabled", - "dns_rsasha1_in_use_to_key_sign_in_dnssec", - "dns_rsasha1_in_use_to_zone_sign_in_dnssec", - "kms_key_not_publicly_accessible", - "kms_key_rotation_enabled" - ] - }, - { - "Id": "ksi-tpr", - "Name": "KSI-TPR: Third-Party Information Resources", - "Description": "A secure cloud service offering will understand, monitor, and manage supply chain risks from third-party information resources", - "Attributes": [ - { - "ItemId": "ksi-tpr", - "Section": "Third-Party Information Resources", - "Service": "gcp" - } - ], - "Checks": [ - "artifacts_container_analysis_enabled", - "gcr_container_scanning_enabled", - "compute_public_address_shodan", - "cloudsql_instance_automated_backups", - "iam_sa_user_managed_key_rotate_90_days", - "iam_service_account_unused", - "gemini_api_disabled" - ] - }, - { - "Id": "ksi-iam-07", - "Name": "KSI-IAM-07: Account Lifecycle Management", - "Description": "Securely manage the lifecycle and privileges of all accounts, roles, and groups", - "Attributes": [ - { - "ItemId": "ksi-iam-07", - "Section": "Identity and Access Management", - "Service": "gcp" - } - ], - "Checks": [ - "apikeys_key_rotated_in_90_days", - "iam_sa_user_managed_key_rotate_90_days", - "iam_sa_user_managed_key_unused", - "iam_service_account_unused", - "compute_instance_default_service_account_in_use" - ] - }, - { - "Id": "ksi-mla-07", - "Name": "KSI-MLA-07: Monitoring and Logging Inventory", - "Description": "Maintain a list of information resources and event types that will be monitored, logged, and audited", - "Attributes": [ - { - "ItemId": "ksi-mla-07", - "Section": "Monitoring, Logging, and Auditing", - "Service": "gcp" - } - ], - "Checks": [ - "iam_audit_logs_enabled", - "iam_cloud_asset_inventory_enabled", - "logging_sink_created", - "compute_subnet_flow_logs_enabled", - "compute_network_dns_logging_enabled" - ] - } - ] -} From 3860cd3dceab27381c0e56595e367e39ddc2ef7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Mon, 14 Sep 2026 16:35:05 +0200 Subject: [PATCH 58/77] feat(compliance): FedRAMP 20x Class C FRR + AWS checks (#12808) --- README.md | 10 +- contrib/k8s/helm/prowler-api/values.yaml | 8 + docs/developer-guide/configurable-checks.mdx | 2 + .../cli/tutorials/configuration_file.mdx | 10 + permissions/prowler-additions-policy.json | 1 + .../cloudformation/prowler-scan-role.yml | 2 + .../aws-inspector2-fips-checks.added.md | 1 + .../fedramp-20x-frr-class-c-2026.added.md | 1 + .../fedramp_20x_frr_class_c_2026.json | 2970 +++++++++++++++++ prowler/config/config.yaml | 8 + prowler/config/schema/aws.py | 14 + .../__init__.py | 0 ...v2_listener_fips_tls_enabled.metadata.json | 43 + .../elbv2_listener_fips_tls_enabled.py | 35 + .../__init__.py | 0 ...findings_kev_within_due_date.metadata.json | 42 + ...or2_active_findings_kev_within_due_date.py | 66 + .../__init__.py | 0 ...wn_exploited_vulnerabilities.metadata.json | 43 + ...ings_no_known_exploited_vulnerabilities.py | 57 + .../__init__.py | 0 ...tive_findings_within_max_age.metadata.json | 43 + ...spector2_active_findings_within_max_age.py | 51 + .../__init__.py | 0 ...r2_coverage_recently_scanned.metadata.json | 43 + .../inspector2_coverage_recently_scanned.py | 57 + .../__init__.py | 0 ..._coverage_scan_status_active.metadata.json | 42 + .../inspector2_coverage_scan_status_active.py | 46 + .../services/inspector2/inspector2_service.py | 201 ++ .../aws/services/inspector2/lib/__init__.py | 0 .../inspector2/lib/vulnerabilities.py | 8 + .../__init__.py | 0 ...fips_security_policy_enabled.metadata.json | 42 + ...fer_server_fips_security_policy_enabled.py | 38 + tests/config/config_test.py | 2 + tests/config/fixtures/config.yaml | 8 + .../elbv2_listener_fips_tls_enabled_test.py | 156 + ...ctive_findings_kev_within_due_date_test.py | 136 + ...no_known_exploited_vulnerabilities_test.py | 149 + ...or2_active_findings_within_max_age_test.py | 140 + ...spector2_coverage_recently_scanned_test.py | 170 + ...ector2_coverage_scan_status_active_test.py | 132 + .../inspector2/inspector2_service_test.py | 220 +- ...erver_fips_security_policy_enabled_test.py | 111 + 45 files changed, 5100 insertions(+), 8 deletions(-) create mode 100644 prowler/changelog.d/aws-inspector2-fips-checks.added.md create mode 100644 prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md create mode 100644 prowler/compliance/fedramp_20x_frr_class_c_2026.json create mode 100644 prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/__init__.py create mode 100644 prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json create mode 100644 prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json create mode 100644 prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py create mode 100644 prowler/providers/aws/services/inspector2/lib/__init__.py create mode 100644 prowler/providers/aws/services/inspector2/lib/vulnerabilities.py create mode 100644 prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/__init__.py create mode 100644 prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json create mode 100644 prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py create mode 100644 tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py create mode 100644 tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py create mode 100644 tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py diff --git a/README.md b/README.md index ad69260cb0..2851101f05 100644 --- a/README.md +++ b/README.md @@ -126,12 +126,12 @@ Every AWS provider scan will enqueue an Attack Paths ingestion job automatically | Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/user-guide/compliance/tutorials/compliance) | [Categories](https://docs.prowler.com/user-guide/cli/tutorials/misc#categories) | Support | Interface | |---|---|---|---|---|---|---| -| AWS | 639 | 86 | 47 | 19 | Official | UI, API, CLI | -| Azure | 191 | 22 | 21 | 16 | Official | UI, API, CLI | -| GCP | 109 | 20 | 19 | 12 | Official | UI, API, CLI | -| Kubernetes | 92 | 7 | 8 | 11 | Official | UI, API, CLI | +| AWS | 662 | 86 | 50 | 19 | Official | UI, API, CLI | +| Azure | 191 | 22 | 25 | 16 | Official | UI, API, CLI | +| GCP | 110 | 20 | 22 | 12 | Official | UI, API, CLI | +| Kubernetes | 92 | 7 | 11 | 11 | Official | UI, API, CLI | | GitHub | 24 | 3 | 2 | 5 | Official | UI, API, CLI | -| M365 | 143 | 10 | 6 | 10 | Official | UI, API, CLI | +| M365 | 144 | 10 | 9 | 10 | Official | UI, API, CLI | | OCI | 52 | 14 | 5 | 10 | Official | UI, API, CLI | | Alibaba Cloud | 63 | 9 | 6 | 9 | Official | UI, API, CLI | | Cloudflare | 29 | 3 | 2 | 5 | Official | UI, API, CLI | diff --git a/contrib/k8s/helm/prowler-api/values.yaml b/contrib/k8s/helm/prowler-api/values.yaml index a6074c7852..5332f9d2eb 100644 --- a/contrib/k8s/helm/prowler-api/values.yaml +++ b/contrib/k8s/helm/prowler-api/values.yaml @@ -212,6 +212,14 @@ mainConfig: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/docs/developer-guide/configurable-checks.mdx b/docs/developer-guide/configurable-checks.mdx index 04a31a8cde..c44f82c5aa 100644 --- a/docs/developer-guide/configurable-checks.mdx +++ b/docs/developer-guide/configurable-checks.mdx @@ -154,6 +154,8 @@ Only fields with a numeric range, a fixed value set, or a length cap are listed. | `max_days_secret_unused` | `7..365` days | | | `max_days_secret_unrotated` | `1..180` days | NIST IA-5: rotate quarterly; CIS ≤90 | | `min_kinesis_stream_retention_hours` | `24..8760` h | 1 day .. 1 year | +| `inspector2_max_days_since_last_scan` | `1..90` days | | +| `inspector2_active_finding_max_age_days` | `1..365` days | Default `192` matches the FedRAMP 20x rule that marks vulnerabilities still open after 192 days as accepted | | `shodan_api_key` | ≤512 chars | | ### Azure diff --git a/docs/user-guide/cli/tutorials/configuration_file.mdx b/docs/user-guide/cli/tutorials/configuration_file.mdx index ac21f5bc6c..a1c14e6626 100644 --- a/docs/user-guide/cli/tutorials/configuration_file.mdx +++ b/docs/user-guide/cli/tutorials/configuration_file.mdx @@ -91,6 +91,8 @@ The following list includes all the AWS checks with configurable variables that | `iam_user_access_not_stale_to_sagemaker` | `max_unused_sagemaker_access_days` | Integer | `90` | | `iam_user_accesskey_unused` | `max_unused_access_keys_days` | Integer | `45` | | `iam_user_console_access_unused` | `max_console_access_days` | Integer | `45` | +| `inspector2_active_findings_within_max_age` | `inspector2_active_finding_max_age_days` | Integer | `192` | +| `inspector2_coverage_recently_scanned` | `inspector2_max_days_since_last_scan` | Integer | `3` | | `kinesis_stream_data_retention_period` | `min_kinesis_stream_retention_hours` | Integer | `168` | | `neptune_cluster_backup_enabled` | `minimum_backup_retention_period` | Integer | `7` | | `opensearch_service_domains_not_publicly_accessible` | `trusted_ips` | List of Strings | `[]` | @@ -490,6 +492,14 @@ aws: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/permissions/prowler-additions-policy.json b/permissions/prowler-additions-policy.json index 25ea46b09d..be17979d2e 100644 --- a/permissions/prowler-additions-policy.json +++ b/permissions/prowler-additions-policy.json @@ -38,6 +38,7 @@ "glue:GetSecurityConfiguration*", "glue:SearchTables", "glue:GetMLTransforms", + "inspector2:BatchGetFindingDetails", "lambda:GetFunction*", "lambda:GetLayerVersion", "logs:FilterLogEvents", diff --git a/permissions/templates/cloudformation/prowler-scan-role.yml b/permissions/templates/cloudformation/prowler-scan-role.yml index d04c8f25d6..d31dea9846 100644 --- a/permissions/templates/cloudformation/prowler-scan-role.yml +++ b/permissions/templates/cloudformation/prowler-scan-role.yml @@ -210,6 +210,7 @@ Resources: - "glue:GetSecurityConfiguration*" - "glue:SearchTables" - "glue:GetMLTransforms" + - "inspector2:BatchGetFindingDetails" - "lambda:GetFunction*" - "logs:FilterLogEvents" - "lightsail:GetRelationalDatabases" @@ -479,6 +480,7 @@ Resources: - "glue:GetSecurityConfiguration*" - "glue:SearchTables" - "glue:GetMLTransforms" + - "inspector2:BatchGetFindingDetails" - "lambda:GetFunction*" - "logs:FilterLogEvents" - "lightsail:GetRelationalDatabases" diff --git a/prowler/changelog.d/aws-inspector2-fips-checks.added.md b/prowler/changelog.d/aws-inspector2-fips-checks.added.md new file mode 100644 index 0000000000..40c36f8062 --- /dev/null +++ b/prowler/changelog.d/aws-inspector2-fips-checks.added.md @@ -0,0 +1 @@ +`inspector2_coverage_scan_status_active`, `inspector2_coverage_recently_scanned`, `inspector2_active_findings_no_known_exploited_vulnerabilities`, `inspector2_active_findings_kev_within_due_date`, `inspector2_active_findings_within_max_age`, `elbv2_listener_fips_tls_enabled` and `transfer_server_fips_security_policy_enabled` checks for AWS provider, covering FedRAMP 20x Class C vulnerability detection, CISA KEV remediation and FIPS cryptography rules; the KEV checks require `inspector2:BatchGetFindingDetails`, now in the Prowler additions policy diff --git a/prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md b/prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md new file mode 100644 index 0000000000..147ad052f3 --- /dev/null +++ b/prowler/changelog.d/fedramp-20x-frr-class-c-2026.added.md @@ -0,0 +1 @@ +`FedRAMP-20x-FRR-Class-C` universal compliance framework (`fedramp_20x_frr_class_c_2026`) with the 158 provider rules of the FedRAMP 20x Class C ruleset from the FedRAMP Consolidated Rules 2026 for AWS, Azure, GCP, Kubernetes and M365 diff --git a/prowler/compliance/fedramp_20x_frr_class_c_2026.json b/prowler/compliance/fedramp_20x_frr_class_c_2026.json new file mode 100644 index 0000000000..f4db7f37bd --- /dev/null +++ b/prowler/compliance/fedramp_20x_frr_class_c_2026.json @@ -0,0 +1,2970 @@ +{ + "framework": "FedRAMP-20x-FRR-Class-C", + "name": "FedRAMP 20x Class C Rules (FRR) 2026", + "version": "2026.09.13.02", + "description": "FedRAMP Rules (FRR) that cloud service providers must follow for a FedRAMP 20x Class C Certification, from the FedRAMP Consolidated Rules for 2026 (release 2026.09.13.02, https://github.com/FedRAMP/rules). Covers the 158 provider rules of the 15 rulesets on the 20x Class C reference page; rules that only bind FedRAMP, agencies, assessors or advisors are excluded, and class-varying rules use their Class C statement. Most rules are program and process obligations that need manual evidence. The Key Security Indicators of the same ruleset are in the fedramp_20x_ksi_2026 framework.", + "icon": "fedramp", + "attributes_metadata": [ + { + "key": "Ruleset", + "label": "Ruleset", + "type": "str", + "required": true, + "enum": [ + "AFC: Addressing FedRAMP Communication", + "CCM: Collaborative Continuous Monitoring", + "CDS: Certification Data Sharing", + "CMU: Cryptographic Module Use", + "CPO: Certification Package Overview", + "FRC: FedRAMP Certification", + "IEC: Incident Evaluation and Communication", + "IVV: Independent Verification and Validation", + "MAS: Minimum Assessment Scope", + "MKT: Marketplace Listing", + "SCG: Secure Configuration Guide", + "SCN: Significant Change Notification", + "SDR: Security Decision Record", + "VDR: Vulnerability Detection and Response", + "VER: Vulnerability Evaluation and Reporting" + ] + }, + { + "key": "Subset", + "label": "Subset", + "type": "str", + "required": true + }, + { + "key": "Force", + "label": "Force", + "type": "str", + "required": true, + "enum": [ + "MUST", + "MUST NOT", + "SHOULD", + "SHOULD NOT", + "MAY" + ] + } + ], + "outputs": { + "table_config": { + "group_by": "Ruleset" + }, + "pdf_config": { + "language": "en", + "primary_color": "#1B3A5C", + "secondary_color": "#2E6DA4", + "bg_color": "#F0F4FA", + "group_by_field": "Ruleset", + "sections": [ + "AFC: Addressing FedRAMP Communication", + "CCM: Collaborative Continuous Monitoring", + "CDS: Certification Data Sharing", + "CMU: Cryptographic Module Use", + "CPO: Certification Package Overview", + "FRC: FedRAMP Certification", + "IEC: Incident Evaluation and Communication", + "IVV: Independent Verification and Validation", + "MAS: Minimum Assessment Scope", + "MKT: Marketplace Listing", + "SCG: Secure Configuration Guide", + "SCN: Significant Change Notification", + "SDR: Security Decision Record", + "VDR: Vulnerability Detection and Response", + "VER: Vulnerability Evaluation and Reporting" + ], + "section_short_names": { + "AFC: Addressing FedRAMP Communication": "AFC", + "CCM: Collaborative Continuous Monitoring": "CCM", + "CDS: Certification Data Sharing": "CDS", + "CMU: Cryptographic Module Use": "CMU", + "CPO: Certification Package Overview": "CPO", + "FRC: FedRAMP Certification": "FRC", + "IEC: Incident Evaluation and Communication": "IEC", + "IVV: Independent Verification and Validation": "IVV", + "MAS: Minimum Assessment Scope": "MAS", + "MKT: Marketplace Listing": "MKT", + "SCG: Secure Configuration Guide": "SCG", + "SCN: Significant Change Notification": "SCN", + "SDR: Security Decision Record": "SDR", + "VDR: Vulnerability Detection and Response": "VDR", + "VER: Vulnerability Evaluation and Reporting": "VER" + }, + "charts": [ + { + "id": "ruleset_compliance", + "type": "horizontal_bar", + "group_by": "Ruleset", + "title": "Compliance Score by FRR Ruleset", + "y_label": "Ruleset", + "x_label": "Compliance %", + "value_source": "compliance_percent", + "color_mode": "by_value" + } + ], + "filter": { + "only_failed": true, + "include_manual": false + } + } + }, + "requirements": [ + { + "id": "AFC-CSO-INB", + "name": "Maintain a FedRAMP Security Inbox", + "description": "Providers MUST establish and maintain an email address to receive messages from FedRAMP; this inbox is a FedRAMP Security Inbox (FSI).", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-NOC", + "name": "Notification of Changes", + "description": "Providers MUST immediately notify FedRAMP of any changes to the email address for their FedRAMP Security Inbox.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-TFG", + "name": "Trust @fedramp.gov and @gsa.gov", + "description": "Providers MUST treat any email originating from an @fedramp.gov or @gsa.gov email address as if it was sent from FedRAMP by default; if such a message is confirmed to originate from someone other than FedRAMP then the FedRAMP Security Inbox rules no longer apply.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-RCV", + "name": "Receive Email Without Disruption", + "description": "Providers MUST receive and react to email messages from FedRAMP without disruption and without requiring additional actions from FedRAMP.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-CRA", + "name": "Complete Required Actions", + "description": "Providers MUST complete the required actions in Emergency or Emergency Test designated messages sent by FedRAMP within the timeframe included in the message.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-EMR", + "name": "Emergency Message Routing", + "description": "Providers MUST route Emergency designated messages sent by FedRAMP to a senior security official for their awareness.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-IMA", + "name": "Important Message Actions", + "description": "Providers SHOULD complete the required actions in Important designated messages sent by FedRAMP within the timeframe specified in the message.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "AFC-CSO-ACK", + "name": "Acknowledge Receipt", + "description": "Providers SHOULD promptly and automatically acknowledge the receipt of messages received from FedRAMP in their FedRAMP Security Inbox.", + "attributes": { + "Ruleset": "AFC: Addressing FedRAMP Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-AVL", + "name": "Report Availability", + "description": "Providers MUST supply an Ongoing Certification Report to all necessary parties every 3 months, covering the entire period since the previous summary, in a consistent format that is human readable; this report MUST include high-level summaries of at least the following information (if applicable): Changes to FedRAMP Certification Data; Planned changes to FedRAMP Certification Data during at least the next 3 months; Accepted vulnerabilities; Transformative changes; Updated recommendations or best practices for security, configuration, usage, or similar aspects of the cloud service offering; A list of all agencies that are directly using the product; FedRAMP Reportable Incidents or an attestation that no such incidents occurred; Lessons learned and changes planned or made as a result of FedRAMP Reportable Incidents (if such occurred)", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-NRD", + "name": "Next Report Date", + "description": "Providers MUST supply the target date for their next Ongoing Certification Report with other public FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-FBM", + "name": "Feedback Mechanism", + "description": "Providers MUST supply an asynchronous mechanism for all necessary parties to provide feedback or ask questions about each Ongoing Certification Report.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-AFS", + "name": "Anonymized Feedback Summary", + "description": "Providers MUST supply an anonymized and desensitized summary of the feedback, questions, and answers about each Ongoing Certification Report as an addendum to the Ongoing Certification Report OR in the next Ongoing Certification Report.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-LSI", + "name": "Limit Sensitive Information", + "description": "Providers MUST NOT irresponsibly disclose sensitive information in an Ongoing Certification Report that would likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-SOR", + "name": "Spread Out Reports", + "description": "Providers SHOULD establish a regular 3 month cycle for Ongoing Certification Reports that is spread out from the beginning, middle, or end of each quarter.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-OCR-RPS", + "name": "Responsible Public Certification Report Sharing", + "description": "Providers MAY responsibly supply some or all of the information an Ongoing Certification Report to the public or other parties if the provider determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "OCR: Ongoing Certification Reports", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-MTG", + "name": "Quarterly Review Meeting", + "description": "Providers with Class C Certifications MUST host a synchronous Quarterly Review every 3 months, open to all necessary parties, to review aspects of the most recent Ongoing Certification Reports that the provider determines are of the most relevance to agencies.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-REG", + "name": "Meeting Registration Info", + "description": "Providers MUST supply either a registration link or a downloadable calendar file with meeting information for Quarterly Reviews to all necessary parties.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-NRD", + "name": "Next Review Date", + "description": "Providers MUST publicly supply the target date for their next Quarterly Review with other public FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-NID", + "name": "No Irresponsible Disclosure", + "description": "Providers MUST NOT irresponsibly disclose sensitive information in a Quarterly Review that would likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-SAR", + "name": "Schedule Around Reports", + "description": "Providers SHOULD regularly schedule Quarterly Reviews to occur at least 3 business days after releasing an Ongoing Certification Report AND within 10 business days of such release.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-ACT", + "name": "Additional Content", + "description": "Providers SHOULD supply additional information in Quarterly Reviews that the provider determines is of interest, use, or otherwise relevant to agencies.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-RTR", + "name": "Record/Transcribe Reviews", + "description": "Providers SHOULD record or transcribe Quarterly Reviews and supply them to all necessary parties.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-RTP", + "name": "Restrict Third Parties", + "description": "Providers SHOULD NOT invite third parties to attend Quarterly Reviews intended for agencies unless they have specific relevance.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-SRR", + "name": "Share Recordings Responsibly", + "description": "Providers MAY responsibly supply recordings or transcriptions of Quarterly Reviews to the public or other parties ONLY if the provider removes all agency information (comments, questions, names, etc.) AND determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CCM-QTR-SCR", + "name": "Share Content Responsibly", + "description": "Providers MAY responsibly supply content prepared for a Quarterly Review to the public or other parties if the provider determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CCM: Collaborative Continuous Monitoring", + "Subset": "QTR: Quarterly Reviews", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-PUB", + "name": "Public Information", + "description": "Providers MUST publicly share up-to-date information about the cloud service offering in both human-readable and JSON formats, including at least the following information that is available and applicable: FedRAMP ID; Service Model; Deployment Model; Business Category; UEI Number; Sales Contact Information; Security Contact Information; Product Website Link; Link to Product Logo; Overall Service Description; Detailed list of specific services and their security categories (see CDS-CSO-SVC (Public Service List) (Service List)); Link to Secure Configuration Guidance; Overview of documentation supplied by the provider for the cloud service offering; Link to Trust Center landing page that includes instructions on accessing information in the trust center; Next Ongoing Certification Report date (see CCM-OCR-NRD (Next Report Date)); Current FedRAMP Recognized independent assessment service", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-SVC", + "name": "Public Service List", + "description": "Providers MUST publicly share a detailed list of specific services and their security categories that are included in the cloud service offering using clear feature or service names that align with standard public marketing materials; this list MUST be complete enough for a potential customer to determine which services are and are not included in the FedRAMP Minimum Assessment Scope without requesting access to underlying FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-FID", + "name": "Always Include FedRAMP ID", + "description": "Providers MUST always include the FedRAMP ID of the related cloud service offering in all FedRAMP Certification Data once assigned, including all reports, notifications, and other communication that results from FedRAMP rules.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-FRC", + "name": "FedRAMP Certification Reports", + "description": "Providers MUST include FedRAMP Certification Reports with their FedRAMP Certification Data without inappropriate modifications, and make such reports available within 2 weeks of receiving the materials from FedRAMP.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-AVR", + "name": "Availability Reporting", + "description": "Providers with Class C Certifications MUST maintain a web service, available to all necessary parties, that indicates current and historical availability of core services within the cloud service offering over at least the past 30 days, including availability incidents, in both human-readable and machine-readable formats; this service MUST be available even if the primary cloud service offering is unavailable.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-UTC", + "name": "Use Trust Centers", + "description": "Providers MUST use a FedRAMP-compatible trust center to store and share FedRAMP Certification Data with all necessary parties.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-CBF", + "name": "Consistency Between Formats", + "description": "Providers MUST use automation to ensure information remains consistent between human-readable and machine-readable formats when FedRAMP Certification Data is provided in both formats.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-RIS", + "name": "Responsible Information Sharing", + "description": "Providers MUST provide sufficient information in FedRAMP Certification Data to support agency authorization decisions but SHOULD NOT include sensitive information that would likely enable a threat actor to gain unauthorized access, cause harm, disrupt operations, or otherwise have a negative adverse impact on the cloud service offering.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-IRP", + "name": "Include Relevant Policies", + "description": "Providers MUST supply all relevant policies and procedures in the FedRAMP Certification Data, including a human-readable and machine-readable reference that explains at least the following about each included policy and procedure: Name of policy or procedure; Name of file, document, web page, etc.; Brief summary of policy or procedure; Word count of document; Current version; Date of last update; Related FedRAMP Practices (if applicable)", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-HAD", + "name": "Historical FedRAMP Certification Data", + "description": "Providers MUST supply snapshots of FedRAMP Certification Data aligned to Ongoing Certification Reports to all necessary parties; these snapshots MUST be available for the duration of FedRAMP Certification.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-PSM", + "name": "Per-Service Certification Materials", + "description": "Providers with Class C Certifications MAY supply per-service FedRAMP Certification materials.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-CSO-RPS", + "name": "Responsible Public Package Sharing", + "description": "Providers MAY responsibly share some or all of the information in a FedRAMP Certification Package publicly or with other parties if the provider determines doing so will NOT likely have an adverse effect on the cloud service offering.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-USH", + "name": "Uninterrupted Sharing", + "description": "Trust centers MUST share FedRAMP Certification Data with all necessary parties without interruption.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-PAC", + "name": "Programmatic Access", + "description": "Trust centers MUST provide documented programmatic access to all FedRAMP Certification Data, including programmatic access to human-readable materials.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-AAI", + "name": "Agency Access Inventory", + "description": "Trust centers MUST maintain an inventory and history of federal agency users or systems with access to FedRAMP Certification Data and MUST make this information available to FedRAMP upon request.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-ACL", + "name": "Access Logging", + "description": "Trust centers MUST log access to FedRAMP Certification Data and store summaries of access for at least six months; such information, as it pertains to specific parties, SHOULD be made available upon request by those parties.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-HMR", + "name": "Human and Machine-Readable Certification Data", + "description": "Trust centers SHOULD make FedRAMP Certification Data available to view and download in both human-readable and machine-readable formats.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-TRC-SSM", + "name": "Self-Service Access Management", + "description": "Trust centers SHOULD include features that encourage all necessary parties to provision and manage access to FedRAMP Certification Data for their users and services directly.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "TRC: FedRAMP-Compatible Trust Centers", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-UTC-AAD", + "name": "Agency Access Denial", + "description": "Providers MUST notify FedRAMP within 5 business days of denying an agency access request for FedRAMP Certification Data.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "UTC: Using a Trust Center", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CDS-UTC-AGA", + "name": "Agency Access", + "description": "Providers SHOULD supply access to the FedRAMP Certification Package with agencies upon request.", + "attributes": { + "Ruleset": "CDS: Certification Data Sharing", + "Subset": "UTC: Using a Trust Center", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CMU-CSO-CMD", + "name": "Cryptographic Module Documentation", + "description": "Providers MUST document the cryptographic modules used in each service (or groups of services that use the same modules) where cryptographic services are used to protect federal customer data, including whether these modules are validated under the NIST Cryptographic Module Validation Program or are update streams of such modules.", + "attributes": { + "Ruleset": "CMU: Cryptographic Module Use", + "Subset": "CSO: Cloud Service Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CMU-CSO-UVM", + "name": "Using Validated Cryptographic Modules", + "description": "Providers with Class C Certifications SHOULD use cryptographic modules or update streams of cryptographic modules with active validations under the NIST Cryptographic Module Validation Program when using cryptographic services to protect federal customer data.", + "attributes": { + "Ruleset": "CMU: Cryptographic Module Use", + "Subset": "CSO: Cloud Service Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "elbv2_listener_fips_tls_enabled", + "transfer_server_fips_security_policy_enabled" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CMU-CSO-CAT", + "name": "Configuration of Agency Tenants", + "description": "Providers SHOULD configure agency tenants by default to use cryptographic services that use cryptographic modules or update streams of cryptographic modules with active validations under the NIST Cryptographic Module Validation Program when such modules are available.", + "attributes": { + "Ruleset": "CMU: Cryptographic Module Use", + "Subset": "CSO: Cloud Service Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSO-OVR", + "name": "Overview of the Cloud Service Offering", + "description": "Providers MUST supply a Certification Package Overview within their FedRAMP Certification Package, in both human-readable and JSON formats, that includes at least all of the information required by the following rules: Certification Package Overview: CPO-CSO-MTD (Certification Package Overview Metadata); Certification Data Sharing: CDS-CSO-PUB (Public Information); Certification Data Sharing: CDS-CSO-SVC (Public Service List); Certification Data Sharing: CDS-CSO-IRP (Include Relevant Policies); Minimum Assessment Scope: MAS-CSO-IIR (Identify Information Resources); Minimum Assessment Scope: MAS-CSO-FLO (Information Flows and Security Categories); Minimum Assessment Scope: MAS-CSO-TPR (Third-Party Information Resources); Using Cryptographic Modules: CMU-CSO-CMD (Cryptographic Module Documentation); Independent Verification and Validation: IVV-CSO-ICP (Inclusion in Certification Package)", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSO-MTD", + "name": "Certification Package Overview Metadata", + "description": "Providers MUST also include the following basic metadata in their Certification Package Overview: Name, title, and contact information of official that is responsible and accountable for the FedRAMP Certification Package; Version; Date and time of last update; Source of update", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSO-OSA", + "name": "Overall Summary of Assessment in Certification Package", + "description": "Providers seeking Class C Certification MUST also include the overall summary of their FedRAMP independent assessment, supplied by the assessor per IVV-IAS-OSA (Overall Summary of Assessment), in their Certification Package Overview.", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "CPO-CSX-CPM", + "name": "Certification Package Maintenance for 20x", + "description": "Providers with 20x Class C Certifications MUST persistently maintain their FedRAMP Certification Package to ensure it is up to date and complete at least once every 2 weeks.", + "attributes": { + "Ruleset": "CPO: Certification Package Overview", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-FCP", + "name": "FedRAMP Certification Profile", + "description": "Providers MUST identify a target FedRAMP Certification Profile and apply all relevant FedRAMP Practices to the cloud service offering.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-PKG", + "name": "FedRAMP Certification Package", + "description": "Providers seeking a Certification MUST supply a complete FedRAMP Certification Package to FedRAMP for initial certification; the FedRAMP Certification Package MUST include at least the following information: Information about the Cloud Service Offering following CPO-CSO-OVR (Overview of the Cloud Service Offering); Implementation, Validation, and Assessment information for each relevant FedRAMP requirement/control/ksi as defined in SDR-CSO-FRR (FedRAMP Rules); A real or example Ongoing Certification Report following CCM-OCR-AVL (Report Availability)", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-JSN", + "name": "FedRAMP JSON Schemas", + "description": "Providers MUST supply machine-readable information in JSON documents that are valid against the corresponding JSON schema when a rule contains a FedRAMP JSON schema, UNLESS otherwise specified in the rule.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-MRA", + "name": "Maintain Responsibility and Accountability", + "description": "Providers MUST maintain responsibility and accountability for the accuracy and completeness of all information in the FedRAMP Certification Package, especially when they engage a third party (such as an independent assessor, advisory service, or external tools) to supply information on their behalf.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSO-POP", + "name": "Pick One Program Certification Type", + "description": "Providers MUST NOT seek both FedRAMP Rev5 Program Certification and FedRAMP 20x Program Certification for the same cloud service offering; pick one type.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-MLF", + "name": "Marketplace Listing First", + "description": "Providers MUST be listed in the FedRAMP Marketplace before applying for FedRAMP Certification, including: FedRAMP Marketplace: MKT-CSO-MLR (Marketplace Listing Requirements); FedRAMP Marketplace: MKT-CSO-PML (Provider Marketplace Listing Requests); FedRAMP Marketplace: MKT-IIP-AGU (Agency Use Cases); FedRAMP Marketplace: MKT-IIP-DCP (Demonstrating Continuous Progress)", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-AFC", + "name": "Applying for FedRAMP Certification", + "description": "Providers MUST complete the FedRAMP Certification Application Form in full to request an initial assessment by FedRAMP.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-FCP", + "name": "Fresh FedRAMP Certification Package", + "description": "Providers MUST supply a fresh initial FedRAMP Certification Package that shows the current status of the cloud service offering as verified and validated by the provider within the previous 7 days.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-FIA", + "name": "Fresh Independent Assessment", + "description": "Providers seeking Class C Certification MUST supply a fresh initial FedRAMP independent assessment that was completed by a FedRAMP Recognized independent assessment service within the previous 3 months.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-NTP", + "name": "No Third-Party Applicants", + "description": "Providers MUST NOT use a third party to apply for a FedRAMP Certification on their behalf; this includes independent assessment services.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-APP-USA", + "name": "Updating Stale Assessments", + "description": "Providers MAY freshen a stale initial independent verification and validation assessment by having a FedRAMP Recognized independent assessment service review any changes between the original assessment and the current status of the cloud service offering in place of a full re-assessment, UNLESS the stale assessment is more than 9 months old.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "APP: Applying for FedRAMP Certification", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-VVK", + "name": "Automated Verification and Validation of Key Security Indicators", + "description": "Providers seeking 20x Class C Certification MUST implement automated methods to persistently verify and validate the accuracy and completeness of Key Security Indicators with at least 2 automated methods for each Key Security Indicator.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-MOT", + "name": "Metrics Over Time for Key Security Indicators", + "description": "Providers seeking 20x Class C Certification MUST supply historical metrics including status from persistent validation over at least the past 6 months for all Key Security Indicators.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-VVR", + "name": "Automated Verification and Validation of FedRAMP Rules", + "description": "Providers seeking 20x Class C Certification SHOULD implement automated methods to persistently verify and validate the accuracy and completeness of the Security Decision Record for FedRAMP rules when applicable.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "FRC-CSX-MAS", + "name": "Application within MAS", + "description": "Providers SHOULD apply ALL Key Security Indicators to ALL aspects of their cloud service offering that are within the FedRAMP Minimum Assessment Scope.", + "attributes": { + "Ruleset": "FRC: FedRAMP Certification", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-EFR", + "name": "Evaluate FedRAMP Reportability", + "description": "Providers MUST promptly evaluate incidents to determine if they affect confidentiality or integrity of federal customer data or are likely to affect confidentiality or integrity of federal customer data; such incidents are FedRAMP Reportable Incidents and must be reported following the FedRAMP Incident Evaluation and Communication rules.", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-DPR", + "name": "Default PAIN Rating", + "description": "Providers MUST treat FedRAMP Reportable Incidents as if they have a Potential Agency Impact N-rating (PAIN) of 5 UNLESS they promptly estimate the PAIN rating following the rule in IEC-CSO-EFI (Estimate Federal Impact).", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-IIR", + "name": "Initial Incident Report", + "description": "Providers with Class C Certifications MUST responsibly notify all affected parties after identifying FedRAMP Reportable Incidents by providing an Initial Incident Report with as much of the following information that is available at the time of reporting and/or the current relevant status for each item: Contact information for the federal incident response coordinator.; Provider's internally assigned tracking identifier; Description of the incident; Timeline of the incident, including start time, time and source of detection, time of completed FedRAMP Reportable Incident evaluation, and other major incident milestones determined by the provider; Historically and currently estimated Potential Agency Impact N-rating (PAIN) of the incident, including an explanation of the evaluation following the requirements in IEC-CSO-EFI (Estimate Federal Impact) (if applicable); Functional impact to federal agency customers (include impact to confidentiality and/or integrity and the impacted federal customer data types); Estimated recovery plan, milestones, and timelines; List of likely affected customer agencies; N1 Initial Incident Report: 1 bizdays; N2 Initial Incident Report: 24 hours; N3 Initial Incident Report: 1 hours; N4 Initial Incident Report: 1 hours; N5 Initial Incident Report: 1 hours", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-OIR", + "name": "Ongoing Incident Reports", + "description": "Providers with Class C Certifications MUST responsibly notify all affected parties of ongoing activity as new information becomes available during incident response for FedRAMP Reportable Incidents, including updates (or lack of updates) to all previously reported information and as much of the following additional information that is available and/or the current relevant status for each item: Observed incident activity; Indicators of compromise; Related Common Vulnerabilities and Exposures (CVE) identifier, if applicable; Root cause; Response and recovery activities; N1 Ongoing Incident Report: 1 bizdays; N2 Ongoing Incident Report: 24 hours; N3 Ongoing Incident Report: 6 hours; N4 Ongoing Incident Report: 6 hours; N5 Ongoing Incident Report: 6 hours", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-FIR", + "name": "Final Incident Report", + "description": "Providers with Class C Certifications MUST responsibly notify all affected parties by providing a Final Incident Report once the incident has been resolved and recovery is complete, including final updates to all previously reported information. N1 Final Incident Report: 1 bizdays; N2 Final Incident Report: 1 bizdays; N3 Final Incident Report: 6 hours; N4 Final Incident Report: 6 hours; N5 Final Incident Report: 6 hours", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-EFI", + "name": "Estimate Federal Impact", + "description": "Providers SHOULD promptly estimate the likely adverse impact of an incident on agency customers to assign a Potential Agency Impact N-rating; this step is called Incident Rating. N1 for a likely minimal customer effect on 1 or more agencies.; N2 for a likely narrow customer effect on 1 or more agencies.; N3 for a likely disruptive customer effect on 1 agency.; N4 for a likely debilitating customer effect on 1 agency or a likely disruptive customer effect on more than 1 agency.; N5 for a likely debilitating customer effect on more than 1 agency.", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IEC-CSO-AIR", + "name": "Automated Incident Reporting", + "description": "Providers SHOULD use automation to minimize human intervention in the process of reporting FedRAMP Reportable Incidents to all affected parties.", + "attributes": { + "Ruleset": "IEC: Incident Evaluation and Communication", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-FIA", + "name": "FedRAMP Independent Assessments", + "description": "Providers with Class C Certifications MUST persistently complete an independent verification and validation assessment of all applicable FedRAMP rules with a FedRAMP Recognized independent assessment service OR FedRAMP at least once per year; this is a FedRAMP independent assessment.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-SEI", + "name": "Supply Evidence of Implementation", + "description": "Providers MUST supply evidence to all necessary assessors of the implementation of the measures that have been documented to meet FedRAMP Practices; this evidence is the result of verification.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-SEE", + "name": "Supply Evidence of Effectiveness", + "description": "Providers MUST supply evidence to all necessary assessors of the effectiveness of the measures that have been implemented to meet FedRAMP Practices; this evidence is the result of validation.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-ICP", + "name": "Inclusion in Certification Package", + "description": "Providers MUST supply the results of FedRAMP independent assessments in their FedRAMP Certification Package without inappropriate modification.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-DUS", + "name": "Document Use of Representative Samples", + "description": "Providers MUST document and explain the use of representative samples during verification and validation when using representative samples as allowed by IVV-CSO-USR (Use Representative Samples).", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-STE", + "name": "Supply Technical Explanations", + "description": "Providers SHOULD supply all necessary assessors with technical explanations, demonstrations, and other relevant supporting information about the technical capabilities they employ to address FedRAMP rules; this SHOULD be supplied as necessary to ensure the assessor can effectively complete verification and validation.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-USR", + "name": "Use Representative Samples", + "description": "Providers MAY use representative samples as appropriate during verification and validation.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSO-RAA", + "name": "Receiving Assessor Advice", + "description": "Providers MAY ask for and accept advice from their assessor during assessment regarding techniques and procedures that will improve their security posture or the effectiveness, clarity, and accuracy of their verification, validation and reporting procedures, UNLESS doing so is likely to compromise the objectivity and integrity of the assessment.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "IVV-CSX-AIA", + "name": "Annual Independent Assessments for 20x", + "description": "Providers with 20x Class C Certifications MUST include all Key Security Indicators in a FedRAMP independent assessment at least once per year.", + "attributes": { + "Ruleset": "IVV: Independent Verification and Validation", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-IIR", + "name": "Identify Information Resources", + "description": "Providers MUST identify a set of information resources to assess for FedRAMP Certification that includes all information resources that are likely to handle federal customer data or likely to impact the confidentiality, integrity, or availability of federal customer data handled by the cloud service offering; this set of information resources is the cloud service offering.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "config_recorder_all_regions_enabled", + "resourceexplorer2_indexes_found" + ], + "azure": [], + "gcp": [ + "iam_cloud_asset_inventory_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "MAS-CSO-FLO", + "name": "Information Flows and Security Categories", + "description": "Providers MUST clearly identify, document, and explain information flows and security categories for ALL information resources or sets of information resources in the cloud service offering.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-TPR", + "name": "Third-Party Information Resources", + "description": "Providers MUST address the potential impact to federal customer data from third-party information resources used by the cloud service offering, ONLY IF MAS-CSO-IIR (Identify Information Resources) APPLIES, by documenting the following information about each applicable third-party information resource: General usage and configuration; Explanation or justification for use; Mitigation measures in place to reduce the potential impact to federal customer data; Compensating controls in place to reduce the potential impact to federal customer data", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-MDI", + "name": "Metadata Inclusion", + "description": "Providers MUST include metadata (including metadata about federal customer data) in the Minimum Assessment Scope ONLY IF MAS-CSO-IIR (Identify Information Resources) APPLIES.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MAS-CSO-SUP", + "name": "Supplemental Information", + "description": "Providers MAY include additional materials about other information resources that are not part of the cloud service offering in a FedRAMP Certification Package supplement; these resources will not be FedRAMP Certified and MUST be clearly marked and separated from the cloud service offering.", + "attributes": { + "Ruleset": "MAS: Minimum Assessment Scope", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-CSO-MLR", + "name": "Marketplace Listing Requirements", + "description": "Providers MUST address at least these FedRAMP rules to apply for a new FedRAMP Marketplace listing OR to request updates to an existing listing: Certification Data Sharing: CDS-CSO-PUB (Public Information)", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-CSO-PML", + "name": "Provider Marketplace Listing Requests", + "description": "Providers MUST notify FedRAMP using the FedRAMP Marketplace Providing Listing Request Form to request a listing in the FedRAMP Marketplace.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-IIP-AGU", + "name": "Agency Use Cases", + "description": "Providers MUST demonstrate that a cloud service offering is intended for one of the following use cases: Direct Use: The product will be used directly by agency customers for integration into a federal information system that falls within the scope of 44 USC § 3506 and will receive an agency Authorization to Operate.; Indirect Use: The product will be included as a third-party information resource in other cloud service offerings that are directly used by agency customers.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "IIP: Provider Responsibilities for Initial Implementation Phase Listings", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-IIP-DCP", + "name": "Demonstrating Continuous Progress", + "description": "Providers MUST demonstrate continuous progress towards a FedRAMP Certification, documented in their Trust Center or website and updated at least quarterly; progress is measured by the provider against documented goals and milestones.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "IIP: Provider Responsibilities for Initial Implementation Phase Listings", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "MKT-IIP-DLA", + "name": "Deadline for Assessment", + "description": "Providers MUST demonstrate that an assessment for a FedRAMP Certification Class B, C, or D has been scheduled within 2 years of initial listing in the Initial Implementation Phase.", + "attributes": { + "Ruleset": "MKT: Marketplace Listing", + "Subset": "IIP: Provider Responsibilities for Initial Implementation Phase Listings", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-RSC", + "name": "Recommended Secure Configuration", + "description": "Providers MUST create, maintain, and make available recommendations for securely configuring their cloud services (the Secure Configuration Guide) that includes at least the following information: Required: Instructions on how to securely access, configure, operate, and decommission top-level administrative accounts that control enterprise access to the entire cloud service offering.; Required: Explanations of security-related settings that can be operated only by top-level administrative accounts and their security implications.; Recommended: Explanations of security-related settings that can be operated only by privileged accounts and their security implications.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-AUP", + "name": "Use Instructions", + "description": "Providers MUST include instructions in the FedRAMP Certification Package that explain how to obtain and use the Secure Configuration Guide.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-PUB", + "name": "Public Secure Configuration Guidance", + "description": "Providers SHOULD make the Secure Configuration Guide available publicly.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-CSO-SDF", + "name": "Secure Defaults", + "description": "Providers SHOULD set all settings to their recommended secure defaults for top-level administrative accounts and privileged accounts when initially provisioned.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-CMP", + "name": "Comparison Capability", + "description": "Providers SHOULD offer the capability to compare all current settings for top-level administrative accounts and privileged accounts to the recommended secure defaults.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-EXP", + "name": "Export Capability", + "description": "Providers SHOULD offer the capability to export all security settings in a machine-readable format.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-API", + "name": "API Capability", + "description": "Providers SHOULD offer the capability to view and adjust security settings via an API or similar capability.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-MRG", + "name": "Machine-Readable Guidance", + "description": "Providers SHOULD also provide the Secure Configuration Guide in a machine-readable format that can be used by customers or third-party tools to compare against current settings.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCG-ENH-VRH", + "name": "Versioning and Release History", + "description": "Providers SHOULD provide versioning and a release history for recommended secure default settings for top-level administrative accounts and privileged accounts as they are adjusted over time.", + "attributes": { + "Ruleset": "SCG: Secure Configuration Guide", + "Subset": "ENH: Enhanced Capabilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-EVA", + "name": "Evaluate Changes", + "description": "Providers MUST evaluate all potential significant changes to determine the type of significant change and follow the appropriate Significant Change Notification rules. Is it a significant change? --> Continue evaluation and follow the Significant Change Notification rules.; If it is, is it an FedRAMP Certification class change? --> This requires a new assessment and cannot be done under the Significant Change Notification rules.; If it is not, is it a routine recurring change? --> Follow the Routine Recurring Change rules (SCN-RTR Routine Recurring Changes).; If it is not, is it a transformative change? --> Follow the Transformative Change rules (SCN-TRF Transformative Changes).; If it is not, then it is an adaptive change --> Follow the Adaptive Change rules (SCN-ADP Adaptive Changes).", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-MAR", + "name": "Maintain Audit Records", + "description": "Providers MUST maintain auditable records of the significant change evaluation activities required by SCN-CSO-EVA (Evaluate Changes) and make them available to FedRAMP as requested.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-INF", + "name": "Required Information", + "description": "Providers MUST include at least the following information in Significant Change Notifications: Service Offering FedRAMP ID; Assessor Name (if applicable); Related Vulnerability (if applicable); Significant Change type and explanation of categorization; Short description of change; Reason for change; Summary of customer impact, including changes to services and customer configuration responsibilities; Plan and timeline for the change, including for the verification, assessment, and/or validation of impacted Key Security Indicators or Rev5 Controls; Copy of the business or security impact analysis; Name and title of approver", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-HIS", + "name": "Historical Notifications", + "description": "Providers MUST keep 12 months of historical Significant Change Notifications available with their FedRAMP Certification Data.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-HRM", + "name": "Human and Machine-Readable Notifications", + "description": "Providers MUST make ALL Significant Change Notifications and related audit records available in human-readable and JSON formats.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-ARI", + "name": "Additional Relevant Information", + "description": "Providers MAY include additional relevant information in Significant Change Notifications.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-NOM", + "name": "Notification Mechanisms", + "description": "Providers MAY notify necessary parties in a variety of ways as long as the mechanism for notification is clearly documented in the FedRAMP Certification Package and easily accessible.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-CSO-EMG", + "name": "Emergency Changes", + "description": "Providers MAY execute significant changes (including transformative changes) during an emergency or incident without following the Significant Change Notification rules in advance. In such emergencies, providers MUST follow all relevant procedures, notify all necessary parties, retroactively provide all Significant Change Notification materials, and complete appropriate assessment after the incident.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-ADP-NTF", + "name": "Notification Requirements", + "description": "Providers MUST notify all necessary parties within 10 business days after finishing adaptive changes, also including the following information: Summary of any new risks identified and/or vulnerabilities resulting from the change (if applicable)", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "ADP: Adaptive Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-RTR-NNR", + "name": "No Notification Requirements", + "description": "Providers SHOULD NOT make formal Significant Change Notifications for routine recurring changes; this type of change is exempted from notification requirements.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "RTR: Routine Recurring Changes", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NIP", + "name": "Notification of Initial Plans", + "description": "Providers MUST notify all necessary parties of initial plans for transformative changes at least 30 business days before starting transformative changes, including a summary of any likely security impacts or changes in risk.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NFP", + "name": "Notification of Final Plans", + "description": "Providers MUST notify all necessary parties of final plans for transformative changes at least 10 business days before starting transformative changes, including updates to all previously sent information.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NAF", + "name": "Notification After Finishing", + "description": "Providers MUST notify all necessary parties within 5 business days after finishing transformative changes, including updates to all previously sent information.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-NAV", + "name": "Notification After Verification", + "description": "Providers MUST notify all necessary parties within 5 business days after completing the verification, assessment, and/or validation of transformative changes, also including the following information: Updates to all previously sent information; Summary of any new risks identified and/or vulnerabilities resulting from the change (if applicable); Copy of the security assessment report (if applicable)", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-UPD", + "name": "Update Documentation", + "description": "Providers MUST publish updated service documentation and other materials to reflect transformative changes within 30 business days after finishing transformative changes.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SCN-TRF-TPR", + "name": "Third-Party Review", + "description": "Providers SHOULD engage a third-party assessor to review the scope and impact of the planned change before starting transformative changes if human validation is necessary; such reviews SHOULD be limited to security decisions that require human validation.", + "attributes": { + "Ruleset": "SCN: Significant Change Notification", + "Subset": "TRF: Transformative Changes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSO-FRR", + "name": "FedRAMP Rules", + "description": "Providers MUST supply a Security Decision Record, in both human-readable and JSON formats, that includes at least all of the following information for each applicable FedRAMP rule: Explanation of how the rule is followed, or an explanation of the reason and resulting risk to customers for not following the rule.; Verification that the implementation is appropriate for the rule, or that the reason for not implementing is accepted by a senior official.; Validation that the implementation is in place and working as intended, or that the reason for not implementing is accepted by a senior official.; Independent verification.; Independent validation.; Any responses or clarifications to the comments in the independent verification or validation.; Rule-specific artifacts (if applicable).", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSO-MTD", + "name": "Security Decision Record Metadata", + "description": "Providers MUST also include the following basic metadata in their Security Decision Record: Version; Date and time of last update; Source of update", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSX-KSI", + "name": "Key Security Indicators", + "description": "Providers MUST also include short and simple high-level summaries of at least the following for each applicable Key Security Indicator: Explanation of measures (and their objectives) that demonstrate the Key Security Indicator, or an explanation of the reason and resulting risk to customers for not having measures available for that Key Security Indicator.; Explanation of the cycle for any measures that are implemented persistently (if applicable).; Verification that the measures demonstrate the Key Security Indicator, or that the reason for not having them is accepted.; Verification that the automation in place is accurate and sufficient to demonstrate appropriate measures for the Key Security Indicator, or that automation is not necessary for each measure.; Validation that the measures are accurately produced and are in place and working as intended, or that the reason for not having them is valid.", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "SDR-CSX-KMT", + "name": "Key Security Indicator Metrics", + "description": "Providers with 20x Class C Certifications MUST also include historical metrics in their Security Decision Record, supplying at least the following information for each applicable Key Security Indicator: Summary of each metric over the past 30 days; Summary of metric up to the past year (where available); All daily metric data up to the past year (where available)", + "attributes": { + "Ruleset": "SDR: Security Decision Record", + "Subset": "CSX: 20x-Specific Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-DET", + "name": "Vulnerability Detection", + "description": "Providers MUST systematically, persistently, and promptly discover and identify vulnerabilities within their cloud service offering using appropriate techniques such as assessment, scanning, threat intelligence, vulnerability disclosure mechanisms, bug bounties, penetration testing, incident response, automated control testing, supply chain monitoring, and other relevant capabilities; this process is called vulnerability detection. Vulnerability detection includes persistently verifying and validating that information resources and processes are operating as intended and documented for FedRAMP Practices.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "ecr_registry_enhanced_scanning_enabled", + "ecr_registry_scan_images_on_push_enabled", + "inspector2_is_enabled", + "securityhub_enabled" + ], + "azure": [ + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_container_images_scan_enabled", + "defender_ensure_defender_cspm_is_on", + "sqlserver_va_periodic_recurring_scans_enabled" + ], + "gcp": [ + "gcr_container_scanning_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-CSO-RES", + "name": "Vulnerability Response", + "description": "Providers MUST systematically, persistently, and promptly track, evaluate, monitor, mitigate, remediate, assess exploitation of, report, and otherwise manage all detected vulnerabilities within their cloud service offering; this process is called vulnerability response.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "ecr_repositories_scan_vulnerabilities_in_latest_image", + "inspector2_active_findings_exist" + ], + "azure": [ + "defender_container_images_resolved_vulnerabilities" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "ecr_repositories_scan_vulnerabilities_in_latest_image", + "ConfigKey": "ecr_repository_vulnerability_minimum_severity", + "Operator": "eq", + "Value": "MEDIUM", + "Provider": "aws" + } + ] + }, + { + "id": "VDR-CSO-FAV", + "name": "Failures Are Vulnerabilities", + "description": "Providers MUST treat problems or failures with their vulnerability detection and response processes as vulnerabilities.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_coverage_scan_status_active" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-DFR", + "name": "Design For Resilience", + "description": "Providers SHOULD make design and architecture decisions for their cloud service offering that mitigate the risk of vulnerabilities by default AND decrease the risk and complexity of vulnerability detection and response.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-ADT", + "name": "Automate Detection", + "description": "Providers SHOULD use automated services to improve and streamline vulnerability detection and response.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "ecr_registry_enhanced_scanning_enabled", + "ecr_registry_scan_images_on_push_enabled", + "inspector2_is_enabled" + ], + "azure": [ + "defender_auto_provisioning_vulnerabilty_assessments_machines_on", + "defender_container_images_scan_enabled", + "sqlserver_va_periodic_recurring_scans_enabled" + ], + "gcp": [ + "gcr_container_scanning_enabled" + ], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-DAC", + "name": "Detect After Changes", + "description": "Providers SHOULD automatically perform vulnerability detection on representative samples of new or significantly changed information resources.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "ecr_registry_scan_images_on_push_enabled", + "inspector2_is_enabled" + ], + "azure": [ + "defender_container_images_scan_enabled" + ], + "gcp": [ + "gcr_container_scanning_enabled" + ], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-MSP", + "name": "Maintain Security", + "description": "Providers SHOULD NOT weaken the security of information resources to facilitate vulnerability scanning, detection, or assessment activities.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-AKE", + "name": "Avoid KEVs", + "description": "Providers SHOULD NOT deploy or otherwise activate new machine-based information resources with Known Exploited Vulnerabilities.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "SHOULD NOT" + }, + "checks": { + "aws": [ + "inspector2_active_findings_no_known_exploited_vulnerabilities" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-CSO-SIR", + "name": "Sampling", + "description": "Providers MAY sample effectively identical information resources, especially machine-based information resources, when performing vulnerability detection UNLESS doing so would decrease the efficiency or effectiveness of vulnerability detection.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "CSO: General Provider Responsibilities", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-NMV", + "name": "Non-Machine Verification and Validation", + "description": "Providers MUST verify and validate the status of non-machine-based information resources at least once every 3 months.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-PDD", + "name": "Persistent Drift Detection", + "description": "Providers with Class C Certifications SHOULD persistently perform vulnerability detection on all information resources that are likely to drift, at least once every 14 days.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_coverage_recently_scanned", + "inspector2_is_enabled", + "securityhub_enabled" + ], + "azure": [ + "defender_ensure_defender_cspm_is_on" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 14, + "Provider": "aws" + }, + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-TFR-PCD", + "name": "Persistently Complete Detection", + "description": "Providers with Class C Certifications SHOULD persistently perform vulnerability detection on all information resources that are NOT likely to drift, at least once every month.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_coverage_recently_scanned" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 30, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-TFR-PVR", + "name": "Mitigation and Remediation Expectations", + "description": "Providers with Class C Certifications SHOULD partially mitigate vulnerabilities, fully mitigate vulnerabilities, or remediate vulnerabilities to a lower Potential Agency Impact N-rating within the timeframes from evaluation shown below, factoring for the current Potential Agency Impact N-rating as defined in VER-EVA-EPA (Estimate Potential Agency Impact), internet reachability, and likely exploitability: N2 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 48 days; N2 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 128 days; N2 Not Likely Exploitable Vulnerability: 192 days; N3 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 16 days; N3 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 32 days; N3 Not Likely Exploitable Vulnerability: 128 days; N4 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 4 days; N4 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 8 days; N4 Not Likely Exploitable Vulnerability: 64 days; N5 Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 2 days; N5 Not Internet-Reachable Vulnerability + Likely Exploitable Vulnerability: 4 days; N5 Not Likely Exploitable Vulnerability: 16 days", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-RMN", + "name": "Remaining Vulnerabilities", + "description": "Providers SHOULD mitigate or remediate remaining vulnerabilities during routine operations as determined necessary by the provider.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "ssm_managed_compliant_patching" + ], + "azure": [ + "defender_ensure_system_updates_are_applied" + ], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-KEV", + "name": "Remediate KEVs", + "description": "Providers SHOULD remediate Known Exploited Vulnerabilities according to the due dates in the CISA Known Exploited Vulnerabilities Catalog (even if the vulnerability has been fully mitigated) as required by CISA Binding Operational Directive (BOD) 26-04 or any successor guidance from CISA.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_active_findings_kev_within_due_date" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VDR-TFR-PSD", + "name": "Persistent Sample Detection", + "description": "Providers with Class C Certifications SHOULD persistently perform vulnerability detection on representative samples of similar machine-based information resources, at least once every 3 days.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [ + "inspector2_coverage_recently_scanned" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 3, + "Provider": "aws" + } + ] + }, + { + "id": "VDR-TFR-MVX", + "name": "Persistent Machine Verification and Validation for 20x", + "description": "Providers of FedRAMP 20x Class C offerings MUST verify and validate the status of machine-based information resources at least once every 3 days.", + "attributes": { + "Ruleset": "VDR: Vulnerability Detection and Response", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [ + "config_recorder_all_regions_enabled", + "inspector2_coverage_recently_scanned", + "securityhub_enabled" + ], + "azure": [ + "defender_ensure_defender_cspm_is_on" + ], + "gcp": [ + "iam_cloud_asset_inventory_enabled" + ], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_coverage_recently_scanned", + "ConfigKey": "inspector2_max_days_since_last_scan", + "Operator": "lte", + "Value": 3, + "Provider": "aws" + }, + { + "Check": "config_recorder_all_regions_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + }, + { + "Check": "securityhub_enabled", + "ConfigKey": "mute_non_default_regions", + "Operator": "eq", + "Value": false, + "Provider": "aws" + } + ] + }, + { + "id": "VER-EVA-ELX", + "name": "Evaluate Exploitability", + "description": "Providers MUST evaluate detected vulnerabilities, considering the context of the cloud service offering, to determine if they are likely exploitable vulnerabilities.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_is_enabled" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EIR", + "name": "Evaluate Internet-Reachability", + "description": "Providers MUST evaluate detected vulnerabilities, considering the context of the cloud service offering, to determine if they are internet-reachable vulnerabilities.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_is_enabled" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EPA", + "name": "Estimate Potential Agency Impact", + "description": "Providers MUST evaluate detected vulnerabilities, considering the context of the cloud service offering, to estimate the potential agency impact of exploitation on government customers AND assign one of the following Potential Agency Impact N-ratings (PAIN): N1: Exploitation could be expected to have minimal customer effects on one or more agencies that use the cloud service offering.; N2: Exploitation could be expected to have narrow customer effects on one or more agencies that use the cloud service offering.; N3: Exploitation could be expected to have a disruptive customer effect on one agency that uses the cloud service offering.; N4: Exploitation could be expected to have a debilitating customer effect on one agency that uses the cloud service offering OR a disruptive customer effect on more than one federal agency that uses the cloud service offering.; N5: Exploitation could be expected to have a debilitating customer effect on more than one agency that uses the cloud service offering.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-AIA", + "name": "Assume It's Automatable", + "description": "Providers MUST assume the exploitation of vulnerabilities can be automated UNLESS they have evidence proving otherwise.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-GRV", + "name": "Group Vulnerabilities", + "description": "Providers SHOULD evaluate detected vulnerabilities, considering the context of the cloud service offering, to identify logical groupings of affected information resources that may improve the efficiency and effectiveness of vulnerability response by consolidating further activity; FedRAMP Vulnerability Detection and Response rules are then applied to these consolidated groupings of vulnerabilities instead of each individual detected instance.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EFP", + "name": "Evaluate False Positives", + "description": "Providers SHOULD evaluate detected vulnerabilities, considering the context of the cloud service offering, to determine if they are false positive vulnerabilities.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-EVA-EFA", + "name": "Evaluation Factors", + "description": "Providers SHOULD consider at least the following factors when considering the context of the cloud service offering to evaluate detected vulnerabilities: Criticality: How important are the systems or information that might be impacted by the vulnerability?; Reachability: How might a threat actor reach the vulnerability and how likely is that?; Exploitability: How easy is it for a threat actor to exploit the vulnerability and how likely is that?; Detectability: How easy is it for a threat actor to become aware of the vulnerability and how likely is that?; Prevalence: How much of the cloud service offering is affected by the vulnerability?; Privilege: How much privileged authority or access is granted or can be gained from exploiting the vulnerability?; Proximate Vulnerabilities: How does this vulnerability interact with previously detected vulnerabilities, especially partially or fully mitigated vulnerabilities?; Known Threats: How might already known threats leverage the vulnerability and how likely is that?", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "EVA: Evaluation", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-PER", + "name": "Persistent Reporting", + "description": "Providers MUST report vulnerability detection and response activity (including persistent verification and validation) to all necessary parties persistently, summarizing ALL activity since the previous report; these reports are FedRAMP Certification Data and are subject to FedRAMP Certification Data Sharing rules.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-VDT", + "name": "Vulnerability Details", + "description": "Providers MUST include the following information (if applicable) on detected vulnerabilities when reporting on vulnerability detection and response activity, UNLESS it is an accepted vulnerability: Provider's internally assigned tracking identifier; Time and source of the detection; Time of completed evaluation; Is it an internet-reachable vulnerability or not?; Is it a likely exploitable vulnerability or not?; Historically and currently estimated Potential Agency Impact N-rating of exploitation; Time and Potential Agency Impact N-rating of each completed and evaluated reduction in Potential Agency Impact N-rating; Estimated time and target Potential Agency Impact N-rating of next reduction in Potential Agency Impact N-rating; Is it currently or is it likely to become an overdue vulnerability or not? If so, explain.; Any supplementary information the provider responsibly determines will help federal agencies assess or mitigate the risk to their federal customer data within the cloud service offering resulting from the vulnerability; Final disposition of the vulnerability", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-AVI", + "name": "Accepted Vulnerability Info", + "description": "Providers MUST include the following information on accepted vulnerabilities when reporting on vulnerability detection and response activity: Provider's internally assigned tracking identifier; Time and source of the detection; Time of completed evaluation; Is it an internet-reachable vulnerability or not?; Is it a likely exploitable vulnerability or not?; Currently estimated Potential Agency Impact N-rating; Explanation of why this is an accepted vulnerability; Any supplementary information the provider determines will responsibly help federal agencies assess or mitigate the risk to their federal customer data within the cloud service offering resulting from the accepted vulnerability", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-NID", + "name": "Responsible Disclosure", + "description": "Providers MUST NOT irresponsibly disclose specific sensitive information about vulnerabilities that would likely lead to exploitation, but MUST disclose sufficient information for informed risk-based decision-making to all necessary parties.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MUST NOT" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-HLO", + "name": "High-Level Overviews", + "description": "Providers SHOULD include high-level overviews of ALL vulnerability detection and response activities conducted during this period for the cloud service offering; this includes vulnerability disclosure programs, bug bounty programs, penetration testing, assessments, etc.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-RPT-RPD", + "name": "Responsible Public Disclosure", + "description": "Providers MAY responsibly disclose vulnerabilities publicly or with other parties if the provider determines doing so will NOT likely lead to exploitation.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "RPT: Reporting", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-MHR", + "name": "Monthly Activity Report", + "description": "Providers MUST report vulnerability detection and response activity to all necessary parties in a consistent format that is human readable at least monthly.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-MAV", + "name": "Mark Accepted Vulnerabilities", + "description": "Providers MUST categorize any vulnerability that is not or will not be fully mitigated or remediated within 192 days of evaluation as an accepted vulnerability.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "MUST" + }, + "checks": { + "aws": [ + "inspector2_active_findings_within_max_age" + ], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + }, + "config_requirements": [ + { + "Check": "inspector2_active_findings_within_max_age", + "ConfigKey": "inspector2_active_finding_max_age_days", + "Operator": "lte", + "Value": 192, + "Provider": "aws" + } + ] + }, + { + "id": "VER-TFR-MRH", + "name": "Historical Activity", + "description": "Providers with Class C Certifications SHOULD make all recent historical vulnerability detection and response activity available in JSON format for automated retrieval by all necessary parties (e.g. using an API service or similar); this information SHOULD be updated persistently, at least once every 14 days.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-EVU", + "name": "Evaluate Vulnerabilities Quickly", + "description": "Providers with Class C Certifications SHOULD evaluate ALL vulnerabilities as required by VER-EVA (Evaluation) within 5 days of detection.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-IRI", + "name": "Internet-Reachable Incidents", + "description": "Providers with Class C Certifications SHOULD treat internet-reachable likely exploitable vulnerabilities where Potential Agency Impact N-rating > 3 as a FedRAMP Reportable Incident until they are partially mitigated vulnerabilities at N3 or below.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "SHOULD" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + }, + { + "id": "VER-TFR-NRI", + "name": "Non-Internet-Reachable Incidents", + "description": "Providers with Class C Certifications MAY treat likely exploitable vulnerabilities that are NOT internet-reachable where Potential Agency Impact N-rating = 5 as a FedRAMP Reportable Incident until they are partially mitigated vulnerabilities at N4 or below.", + "attributes": { + "Ruleset": "VER: Vulnerability Evaluation and Reporting", + "Subset": "TFR: Timeframes", + "Force": "MAY" + }, + "checks": { + "aws": [], + "azure": [], + "gcp": [], + "kubernetes": [], + "m365": [] + } + } + ] +} diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 46127c9699..0c7551d634 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -190,6 +190,14 @@ aws: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/prowler/config/schema/aws.py b/prowler/config/schema/aws.py index 75fa5f73c0..c46d848650 100644 --- a/prowler/config/schema/aws.py +++ b/prowler/config/schema/aws.py @@ -333,6 +333,20 @@ class AWSProviderConfig(ProviderConfigBase): description="Highest severity tolerated for ECR images.", ) + # --- Inspector2 ------------------------------------------------------- + inspector2_max_days_since_last_scan: Optional[int] = Field( + default=None, + ge=1, + le=90, + description="Days since Inspector2 last scanned a covered resource. Range: 1..90.", + ) + inspector2_active_finding_max_age_days: Optional[int] = Field( + default=None, + ge=1, + le=365, + description="Days an Inspector2 finding can stay active since first observed. Range: 1..365.", + ) + # --- Trusted Advisor -------------------------------------------------- verify_premium_support_plans: Optional[bool] = None diff --git a/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/__init__.py b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json new file mode 100644 index 0000000000..9e321f7c54 --- /dev/null +++ b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "elbv2_listener_fips_tls_enabled", + "CheckTitle": "ELBv2 HTTPS/TLS listeners use a FIPS TLS security policy", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "elbv2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "low", + "ResourceType": "AwsElbv2LoadBalancer", + "ResourceGroup": "network", + "Description": "**ELBv2 HTTPS and TLS listeners** are assessed for use of a **FIPS** TLS security policy (`ELBSecurityPolicy-*-FIPS-*`). FIPS policies terminate TLS with the AWS-LC FIPS validated cryptographic module.", + "Risk": "Listeners without a FIPS policy terminate TLS with cryptographic modules that are not FIPS 140 validated, which does not meet requirements to protect federal or regulated data with **NIST CMVP validated cryptography**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/elasticloadbalancing/latest/application/describe-ssl-policies.html", + "https://docs.aws.amazon.com/elasticloadbalancing/latest/network/describe-ssl-policies.html", + "https://aws.amazon.com/compliance/fips/" + ], + "Remediation": { + "Code": { + "CLI": "aws elbv2 modify-listener --listener-arn --ssl-policy ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::ElasticLoadBalancingV2::Listener\n Properties:\n LoadBalancerArn: \n Protocol: HTTPS\n Port: 443\n DefaultActions:\n - Type: forward\n TargetGroupArn: \n Certificates:\n - CertificateArn: \n SslPolicy: ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04 # FIX: uses a FIPS TLS policy\n```", + "Other": "1. In the AWS Console, go to EC2 > Load Balancers\n2. Select the load balancer and open the Listeners tab\n3. Select each HTTPS/TLS listener and choose Edit\n4. Set Security policy to a FIPS policy such as ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04\n5. Save changes", + "Terraform": "```hcl\nresource \"aws_lb_listener\" \"\" {\n load_balancer_arn = \"\"\n port = 443\n protocol = \"HTTPS\"\n ssl_policy = \"ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04\" # FIX: FIPS TLS policy\n certificate_arn = \"\"\n\n default_action {\n type = \"forward\"\n target_group_arn = \"\"\n }\n}\n```" + }, + "Recommendation": { + "Text": "Use a **FIPS** TLS security policy, such as `ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04`, on every HTTPS and TLS listener that carries federal or regulated data.", + "Url": "https://hub.prowler.com/check/elbv2_listener_fips_tls_enabled" + } + }, + "Categories": [ + "encryption" + ], + "DependsOn": [], + "RelatedTo": [ + "elbv2_insecure_ssl_ciphers", + "elbv2_listener_pqc_tls_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py new file mode 100644 index 0000000000..3a9d07f4ba --- /dev/null +++ b/prowler/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled.py @@ -0,0 +1,35 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.elbv2.elbv2_client import elbv2_client + + +class elbv2_listener_fips_tls_enabled(Check): + """Ensure every ELBv2 HTTPS or TLS listener uses a FIPS TLS security policy.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether each load balancer terminates HTTPS/TLS with a FIPS policy.""" + findings = [] + for lb in elbv2_client.loadbalancersv2.values(): + if lb.listener_discovery_failed: + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=lb) + tls_listeners = { + listener_arn: listener + for listener_arn, listener in lb.listeners.items() + if listener.protocol in ("HTTPS", "TLS") + } + non_fips_listeners = [ + f"{listener.protocol}:{listener.port} ({listener_arn}) uses {listener.ssl_policy or ''}" + for listener_arn, listener in tls_listeners.items() + if "FIPS" not in (listener.ssl_policy or "").split("-") + ] + if not tls_listeners: + report.status = "PASS" + report.status_extended = f"ELBv2 {lb.name} has no HTTPS/TLS listeners." + elif non_fips_listeners: + report.status = "FAIL" + report.status_extended = f"ELBv2 {lb.name} has HTTPS/TLS listeners without a FIPS TLS security policy: {', '.join(non_fips_listeners)}." + else: + report.status = "PASS" + report.status_extended = f"ELBv2 {lb.name} has all HTTPS/TLS listeners using a FIPS TLS security policy." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json new file mode 100644 index 0000000000..3795a96fae --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_active_findings_kev_within_due_date", + "CheckTitle": "Inspector2 has no active findings for CISA Known Exploited Vulnerabilities past their remediation due date", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "critical", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** active findings for **CISA Known Exploited Vulnerabilities** are compared with the remediation due date (`dateDue`) that CISA assigns to each entry of the KEV catalog. Findings that are still active after that date are reported.\n\nThe result is reported per Region where Inspector is enabled.", + "Risk": "CISA due dates reflect **active exploitation**. Missing them keeps exploited vulnerabilities open beyond the window CISA sets for federal agencies and shows that vulnerability response is not keeping pace with real threats.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetFindingDetails.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the AWS Console, open Amazon Inspector > Findings\n2. Filter by Vulnerability ID for each overdue CVE reported by this check\n3. Patch or upgrade the affected packages, rebuild container images or update Lambda runtimes\n4. If a fix is not available, apply the mitigations listed in the CISA catalog entry\n5. Confirm the findings move to Closed", + "Terraform": "" + }, + "Recommendation": { + "Text": "Track every KEV finding against its **CISA due date** and remediate before it passes. When no fix exists yet, apply the vendor or CISA mitigations and document the residual risk.", + "Url": "https://hub.prowler.com/check/inspector2_active_findings_kev_within_due_date" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_active_findings_no_known_exploited_vulnerabilities" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py new file mode 100644 index 0000000000..e0ec8ddd30 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date.py @@ -0,0 +1,66 @@ +from datetime import datetime, timezone + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) +from prowler.providers.aws.services.inspector2.lib.vulnerabilities import ( + summarize_vulnerabilities, +) + + +class inspector2_active_findings_kev_within_due_date(Check): + """Ensure active Inspector2 findings for CISA KEVs are not past their CISA due date.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report, per Region, whether any CISA KEV finding is past its remediation due date.""" + findings = [] + now = datetime.now(timezone.utc) + known_exploited = inspector2_client.known_exploited_vulnerabilities + lookup_failed = inspector2_client.vulnerability_lookup_failed + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + if inspector.findings is None: + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 findings could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListFindings permission." + ) + findings.append(report) + continue + vulnerability_ids = { + finding.vulnerability_id + for finding in inspector.findings + if finding.vulnerability_id + } + overdue = sorted( + f"{vulnerability_id} (due {known_exploited[vulnerability_id].date_due.date().isoformat()})" + for vulnerability_id in known_exploited.keys() & vulnerability_ids + if known_exploited[vulnerability_id].date_due + and known_exploited[vulnerability_id].date_due < now + ) + unverified_ids = sorted(vulnerability_ids & lookup_failed) + if overdue: + report.status = "FAIL" + report.status_extended = ( + f"Inspector2 has active findings in region {inspector.region} for CISA " + "Known Exploited Vulnerabilities past their remediation due date: " + f"{summarize_vulnerabilities(overdue)}." + ) + elif unverified_ids: + report.status = "MANUAL" + report.status_extended = ( + "Inspector2 could not verify the CISA Known Exploited Vulnerabilities status of " + f"{summarize_vulnerabilities(unverified_ids)} in region {inspector.region}; " + "verify the inspector2:BatchGetFindingDetails permission." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Inspector2 has no active findings in region {inspector.region} for CISA " + "Known Exploited Vulnerabilities past their remediation due date." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json new file mode 100644 index 0000000000..5072ebd6a6 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_active_findings_no_known_exploited_vulnerabilities", + "CheckTitle": "Inspector2 has no active findings for CISA Known Exploited Vulnerabilities", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "high", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** active findings are cross-referenced with the **CISA Known Exploited Vulnerabilities (KEV)** catalog, using the CISA data that Inspector returns in the finding details (`BatchGetFindingDetails`) of each CVE.\n\nThe result is reported per Region where Inspector is enabled.", + "Risk": "KEV entries are vulnerabilities **confirmed as exploited in the wild**. Workloads carrying them are prime targets for initial access and ransomware, enabling remote code execution, data exfiltration and lateral movement.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://www.cisa.gov/known-exploited-vulnerabilities-catalog", + "https://docs.aws.amazon.com/inspector/v2/APIReference/API_BatchGetFindingDetails.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the AWS Console, open Amazon Inspector > Findings\n2. Filter by Vulnerability ID for each CVE reported by this check\n3. Patch or upgrade the affected packages, rebuild container images or update Lambda runtimes\n4. Confirm the findings move to Closed", + "Terraform": "" + }, + "Recommendation": { + "Text": "Remediate KEV findings before any other vulnerability: patch or upgrade the affected packages, rebuild and redeploy container images, and stop deploying new resources that carry **known exploited vulnerabilities**.", + "Url": "https://hub.prowler.com/check/inspector2_active_findings_no_known_exploited_vulnerabilities" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_active_findings_exist", + "inspector2_active_findings_kev_within_due_date" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py new file mode 100644 index 0000000000..e483205cb1 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities.py @@ -0,0 +1,57 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) +from prowler.providers.aws.services.inspector2.lib.vulnerabilities import ( + summarize_vulnerabilities, +) + + +class inspector2_active_findings_no_known_exploited_vulnerabilities(Check): + """Ensure no active Inspector2 finding is a CISA Known Exploited Vulnerability.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report, per Region, whether any active finding is a CISA Known Exploited Vulnerability.""" + findings = [] + known_exploited = inspector2_client.known_exploited_vulnerabilities + lookup_failed = inspector2_client.vulnerability_lookup_failed + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + if inspector.findings is None: + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 findings could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListFindings permission." + ) + findings.append(report) + continue + vulnerability_ids = { + finding.vulnerability_id + for finding in inspector.findings + if finding.vulnerability_id + } + kev_ids = sorted(known_exploited.keys() & vulnerability_ids) + unverified_ids = sorted(vulnerability_ids & lookup_failed) + if kev_ids: + report.status = "FAIL" + report.status_extended = ( + f"Inspector2 has active findings in region {inspector.region} for CISA " + f"Known Exploited Vulnerabilities: {summarize_vulnerabilities(kev_ids)}." + ) + elif unverified_ids: + report.status = "MANUAL" + report.status_extended = ( + "Inspector2 could not verify the CISA Known Exploited Vulnerabilities status of " + f"{summarize_vulnerabilities(unverified_ids)} in region {inspector.region}; " + "verify the inspector2:BatchGetFindingDetails permission." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Inspector2 has no active findings in region {inspector.region} for CISA " + "Known Exploited Vulnerabilities." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json new file mode 100644 index 0000000000..7846da4f05 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_active_findings_within_max_age", + "CheckTitle": "Inspector2 has no active findings older than the configured maximum age", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/Patch Management", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** active findings are evaluated against the configurable `inspector2_active_finding_max_age_days` threshold (192 days by default), using the time since each finding was first observed (`firstObservedAt`). Suppressed and closed findings are not active and are not evaluated.\n\nThe result is reported per Region where Inspector is enabled.", + "Risk": "Findings left open for months show that **vulnerability response** is not keeping up. Long-lived vulnerabilities give attackers time to discover and exploit them, and a backlog that is neither fixed nor formally accepted hides real risk from decision makers.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/inspector/latest/user/findings-understanding.html", + "https://docs.aws.amazon.com/inspector/latest/user/findings-managing-supression-rules.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the Amazon Inspector console, open Findings and filter by Finding status = Active\n2. Remediate the findings first observed longest ago\n3. For vulnerabilities you formally accept, choose Suppression rules in the navigation pane and create a rule so they stop counting as active", + "Terraform": "" + }, + "Recommendation": { + "Text": "Remediate findings within your vulnerability response timeframes. Vulnerabilities you decide not to fix should be formally **accepted** and suppressed with a documented justification instead of staying active indefinitely.", + "Url": "https://hub.prowler.com/check/inspector2_active_findings_within_max_age" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_active_findings_exist" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py new file mode 100644 index 0000000000..220ee3c9cd --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age.py @@ -0,0 +1,51 @@ +from datetime import datetime, timedelta, timezone + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) + + +class inspector2_active_findings_within_max_age(Check): + """Ensure no Inspector2 finding stays active longer than the configured days.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report, per Region, whether any active finding is older than the allowed days.""" + findings = [] + max_age_days = inspector2_client.audit_config.get( + "inspector2_active_finding_max_age_days", 192 + ) + max_age = timedelta(days=max_age_days) + now = datetime.now(timezone.utc) + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + if inspector.findings is None: + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 findings could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListFindings permission." + ) + findings.append(report) + continue + stale_ages = [ + now - finding.first_observed_at + for finding in inspector.findings + if finding.first_observed_at + and now - finding.first_observed_at > max_age + ] + if stale_ages: + report.status = "FAIL" + report.status_extended = ( + f"Inspector2 has {len(stale_ages)} active findings in region {inspector.region} " + f"first observed more than {max_age_days} days ago, the oldest {max(stale_ages).days} days ago." + ) + else: + report.status = "PASS" + report.status_extended = ( + f"Inspector2 has no active findings in region {inspector.region} " + f"first observed more than {max_age_days} days ago." + ) + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json new file mode 100644 index 0000000000..8fc174f17f --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.metadata.json @@ -0,0 +1,43 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_coverage_recently_scanned", + "CheckTitle": "Inspector2 covered resource was scanned within the configured number of days", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** coverage is evaluated for every actively monitored resource. The time since the resource was last scanned (`lastScannedAt`) is compared with the configurable `inspector2_max_days_since_last_scan` threshold (3 days by default).\n\nResources still pending their first scan are not evaluated.", + "Risk": "Stale scans leave **newly published CVEs** and configuration **drift** undetected. A resource that has not been rescanned for weeks can keep running exploitable packages long after a fix is available.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/inspector/latest/user/assessing-coverage.html", + "https://docs.aws.amazon.com/inspector/latest/user/scanning-ecr.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the Amazon Inspector console, choose Account management and review the Last scanned at value in the Instances, Container images and Lambda functions tabs\n2. For EC2 instances, confirm the SSM Agent is healthy or, under General settings > EC2 scanning settings, set the scan mode to hybrid\n3. For ECR images, increase the Amazon ECR re-scan duration in the Amazon Inspector settings\n4. Confirm the resources are rescanned", + "Terraform": "" + }, + "Recommendation": { + "Text": "Keep continuous scanning healthy: use **hybrid** EC2 scanning so instances without a working SSM agent are still scanned, set a long ECR **rescan duration** for images in use, and investigate every resource whose last scan is older than the allowed window.", + "Url": "https://hub.prowler.com/check/inspector2_coverage_recently_scanned" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_is_enabled", + "inspector2_coverage_scan_status_active" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py new file mode 100644 index 0000000000..0e5a3bf6fd --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned.py @@ -0,0 +1,57 @@ +from datetime import datetime, timedelta, timezone + +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) + +PENDING_SCAN_REASONS = { + "PENDING_INITIAL_SCAN", + "PENDING_REVIVAL_SCAN", + "SCAN_IN_PROGRESS", +} + + +class inspector2_coverage_recently_scanned(Check): + """Ensure Inspector2 scanned every actively covered resource within the configured days.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether each actively covered resource was scanned within the allowed days.""" + findings = [] + max_days = inspector2_client.audit_config.get( + "inspector2_max_days_since_last_scan", 3 + ) + max_elapsed = timedelta(days=max_days) + now = datetime.now(timezone.utc) + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + if inspector.coverage is None: + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 coverage could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListCoverage permission." + ) + findings.append(report) + continue + for resource in inspector.coverage: + if resource.scan_status_code != "ACTIVE": + continue + if ( + resource.last_scanned_at is None + and resource.scan_status_reason in PENDING_SCAN_REASONS + ): + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=resource) + if resource.last_scanned_at is None: + report.status = "FAIL" + report.status_extended = f"{resource.resource_type} {resource.id} has no recorded Inspector2 scan." + elif now - resource.last_scanned_at > max_elapsed: + report.status = "FAIL" + report.status_extended = f"{resource.resource_type} {resource.id} was last scanned by Inspector2 more than {max_days} days ago." + else: + report.status = "PASS" + report.status_extended = f"{resource.resource_type} {resource.id} was last scanned by Inspector2 within the last {max_days} days." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/__init__.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json new file mode 100644 index 0000000000..0488e5097f --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "aws", + "CheckID": "inspector2_coverage_scan_status_active", + "CheckTitle": "Inspector2 covered resource is actively scanned", + "CheckType": [ + "Software and Configuration Checks/Vulnerabilities/CVE", + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "inspector2", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Other", + "ResourceGroup": "security", + "Description": "**Amazon Inspector** coverage is evaluated for every resource it tracks (EC2 instances, ECR images and repositories, Lambda functions). A resource whose scan status is `INACTIVE`, for example because of `UNMANAGED_EC2_INSTANCE`, `NO_INVENTORY`, `UNSUPPORTED_OS` or `ACCESS_DENIED`, is not being scanned for vulnerabilities.\n\nStopped, terminated, tag-excluded and aged-out resources are not evaluated.", + "Risk": "Resources that Inspector cannot scan silently fall out of **vulnerability detection**. New CVEs affecting those workloads are never reported, so exploitable software can stay deployed while the account still appears covered.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/inspector/latest/user/assessing-coverage.html", + "https://docs.aws.amazon.com/inspector/latest/user/scanning-ec2.html" + ], + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "1. In the Amazon Inspector console, choose Account management\n2. Open the Instances, Container images or Lambda functions tab and review the resources that are not actively scanned\n3. Fix the reported cause: register EC2 instances with Systems Manager or set the EC2 scan mode to hybrid, use supported operating systems and runtimes, and grant access to the required encryption keys\n4. Confirm the resource is actively scanned", + "Terraform": "" + }, + "Recommendation": { + "Text": "Resolve the reason reported in each inactive resource's scan status so Inspector can scan every in-scope workload. Register EC2 instances with **Systems Manager** or enable **hybrid scanning**, keep operating systems and runtimes supported, and treat scanning gaps as vulnerabilities to track.", + "Url": "https://hub.prowler.com/check/inspector2_coverage_scan_status_active" + } + }, + "Categories": [ + "vulnerabilities" + ], + "DependsOn": [], + "RelatedTo": [ + "inspector2_is_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py new file mode 100644 index 0000000000..c1cd63cc02 --- /dev/null +++ b/prowler/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active.py @@ -0,0 +1,46 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.inspector2.inspector2_client import ( + inspector2_client, +) + +NOT_APPLICABLE_SCAN_REASONS = { + "EC2_INSTANCE_STOPPED", + "EXCLUDED_BY_TAG", + "NO_RESOURCES_FOUND", + "PENDING_DISABLE", + "RESOURCE_TERMINATED", + "SCAN_ELIGIBILITY_EXPIRED", +} + + +class inspector2_coverage_scan_status_active(Check): + """Ensure Inspector2 is actively scanning every covered resource.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether Inspector2 is actively scanning each covered resource.""" + findings = [] + for inspector in inspector2_client.inspectors: + if inspector.status != "ENABLED": + continue + if inspector.coverage is None: + report = Check_Report_AWS(metadata=self.metadata(), resource=inspector) + report.status = "MANUAL" + report.status_extended = ( + f"Inspector2 coverage could not be retrieved in region {inspector.region}; " + "verify the inspector2:ListCoverage permission." + ) + findings.append(report) + continue + for resource in inspector.coverage: + if resource.scan_status_reason in NOT_APPLICABLE_SCAN_REASONS: + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=resource) + if resource.scan_status_code == "ACTIVE": + report.status = "PASS" + report.status_extended = f"Inspector2 is actively scanning {resource.resource_type} {resource.id}." + else: + report.status = "FAIL" + reason = resource.scan_status_reason or "no reason reported" + report.status_extended = f"Inspector2 is not scanning {resource.resource_type} {resource.id}: {reason}." + findings.append(report) + return findings diff --git a/prowler/providers/aws/services/inspector2/inspector2_service.py b/prowler/providers/aws/services/inspector2/inspector2_service.py index cc6dac7413..6acf186a66 100644 --- a/prowler/providers/aws/services/inspector2/inspector2_service.py +++ b/prowler/providers/aws/services/inspector2/inspector2_service.py @@ -1,16 +1,33 @@ +from datetime import datetime +from typing import Optional + from pydantic.v1 import BaseModel from prowler.lib.logger import logger +from prowler.lib.scan_filters.scan_filters import is_resource_filtered from prowler.providers.aws.lib.service.service import AWSService +FINDING_DETAILS_BATCH_SIZE = 10 + class Inspector2(AWSService): def __init__(self, provider): # Call AWSService's __init__ super().__init__(__class__.__name__, provider) self.inspectors = [] + self.known_exploited_vulnerabilities = {} + self.vulnerability_lookup_failed = set() self.__threading_call__(self._batch_get_account_status) self.__threading_call__(self._list_active_findings, self.inspectors) + enabled_inspectors = [ + inspector for inspector in self.inspectors if inspector.status == "ENABLED" + ] + self.__threading_call__(self._list_findings, enabled_inspectors) + self.__threading_call__(self._list_coverage, enabled_inspectors) + self.__threading_call__( + self._batch_get_finding_details, + self._get_finding_detail_batches(enabled_inspectors), + ) def _batch_get_account_status(self, regional_client): # We use this function to check if inspector2 is enabled @@ -59,6 +76,188 @@ class Inspector2(AWSService): f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + def _list_findings(self, inspector): + """Store the active findings of the audited account for an enabled Region.""" + logger.info("Inspector2 - Listing active findings details...") + try: + paginator = self.regional_clients[inspector.region].get_paginator( + "list_findings" + ) + findings = [] + for page in paginator.paginate( + filterCriteria={ + "awsAccountId": [ + {"comparison": "EQUALS", "value": self.audited_account}, + ], + "findingStatus": [{"comparison": "EQUALS", "value": "ACTIVE"}], + }, + PaginationConfig={"PageSize": 100}, + ): + for finding in page.get("findings", []): + findings.append( + Finding( + arn=finding.get("findingArn", ""), + type=finding.get("type", ""), + severity=finding.get("severity", ""), + first_observed_at=finding.get("firstObservedAt"), + vulnerability_id=finding.get( + "packageVulnerabilityDetails", {} + ).get("vulnerabilityId"), + resource_ids=[ + resource["id"] + for resource in finding.get("resources", []) + if resource.get("id") + ], + ) + ) + inspector.findings = findings + except Exception as error: + logger.error( + f"{inspector.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + def _list_coverage(self, inspector): + """Store the resources Inspector2 covers in an enabled Region, respecting audit resources.""" + logger.info("Inspector2 - Listing coverage...") + try: + paginator = self.regional_clients[inspector.region].get_paginator( + "list_coverage" + ) + coverage = [] + for page in paginator.paginate( + filterCriteria={ + "accountId": [ + {"comparison": "EQUALS", "value": self.audited_account}, + ], + }, + PaginationConfig={"PageSize": 200}, + ): + for covered_resource in page.get("coveredResources", []): + resource_id = covered_resource.get("resourceId", "") + resource_type = covered_resource.get("resourceType", "") + scan_status = covered_resource.get("scanStatus", {}) + arn = self._get_covered_resource_arn( + resource_type, resource_id, inspector.region + ) + if self.audit_resources and not is_resource_filtered( + arn, self.audit_resources + ): + continue + coverage.append( + CoveredResource( + id=resource_id, + arn=arn, + region=inspector.region, + resource_type=resource_type, + scan_type=covered_resource.get("scanType", ""), + scan_status_code=scan_status.get("statusCode", ""), + scan_status_reason=scan_status.get("reason", ""), + last_scanned_at=covered_resource.get("lastScannedAt"), + ) + ) + inspector.coverage = coverage + except Exception as error: + logger.error( + f"{inspector.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + def _get_covered_resource_arn(self, resource_type, resource_id, region): + """Return the ARN of a covered resource, building it for EC2 instance IDs.""" + if resource_type == "AWS_EC2_INSTANCE" and not resource_id.startswith("arn:"): + return f"arn:{self.audited_partition}:ec2:{region}:{self.audited_account}:instance/{resource_id}" + return resource_id + + @staticmethod + def _get_finding_detail_batches(inspectors): + """Group one active finding per CVE into finding details batches per Region.""" + representatives = {} + for inspector in inspectors: + for finding in inspector.findings or []: + if finding.vulnerability_id and finding.vulnerability_id.startswith( + "CVE-" + ): + representatives.setdefault( + finding.vulnerability_id, (inspector.region, finding.arn) + ) + findings_by_region = {} + for vulnerability_id, (region, finding_arn) in representatives.items(): + findings_by_region.setdefault(region, []).append( + (finding_arn, vulnerability_id) + ) + return [ + (region, findings[index : index + FINDING_DETAILS_BATCH_SIZE]) + for region, findings in findings_by_region.items() + for index in range(0, len(findings), FINDING_DETAILS_BATCH_SIZE) + ] + + def _batch_get_finding_details(self, batch): + """Record the CISA KEV data of the CVEs in a batch, flagging failed lookups.""" + region, findings = batch + vulnerability_ids = dict(findings) + logger.info("Inspector2 - Getting finding details...") + try: + response = self.regional_clients[region].batch_get_finding_details( + findingArns=list(vulnerability_ids) + ) + for detail in response.get("findingDetails", []): + vulnerability_id = vulnerability_ids.get(detail.get("findingArn")) + cisa_data = detail.get("cisaData") + if vulnerability_id and cisa_data: + self.known_exploited_vulnerabilities[vulnerability_id] = ( + KnownExploitedVulnerability( + id=vulnerability_id, + date_added=cisa_data.get("dateAdded"), + date_due=cisa_data.get("dateDue"), + ) + ) + for detail_error in response.get("errors", []): + # Inspector has no intelligence for the CVE, so it cannot be a KEV + if detail_error.get("errorCode") == "FINDING_DETAILS_NOT_FOUND": + continue + vulnerability_id = vulnerability_ids.get(detail_error.get("findingArn")) + if vulnerability_id: + self.vulnerability_lookup_failed.add(vulnerability_id) + logger.error( + f"{region} -- {detail_error.get('errorCode')} getting finding details for {vulnerability_id}: {detail_error.get('errorMessage')}" + ) + except Exception as error: + self.vulnerability_lookup_failed.update(vulnerability_ids.values()) + logger.error( + f"{region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + +class Finding(BaseModel): + """Active Inspector2 finding.""" + + arn: str + type: str + severity: str + first_observed_at: Optional[datetime] + vulnerability_id: Optional[str] + resource_ids: list[str] = [] + + +class CoveredResource(BaseModel): + """Resource tracked by Inspector2 coverage.""" + + id: str + arn: str + region: str + resource_type: str + scan_type: str + scan_status_code: str + scan_status_reason: str + last_scanned_at: Optional[datetime] + + +class KnownExploitedVulnerability(BaseModel): + """CISA Known Exploited Vulnerability data of a CVE.""" + + id: str + date_added: Optional[datetime] + date_due: Optional[datetime] + class Inspector(BaseModel): id: str @@ -70,3 +269,5 @@ class Inspector(BaseModel): lambda_status: str lambda_code_status: str active_findings: bool = None + findings: Optional[list[Finding]] = None + coverage: Optional[list[CoveredResource]] = None diff --git a/prowler/providers/aws/services/inspector2/lib/__init__.py b/prowler/providers/aws/services/inspector2/lib/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/inspector2/lib/vulnerabilities.py b/prowler/providers/aws/services/inspector2/lib/vulnerabilities.py new file mode 100644 index 0000000000..7544f0de4d --- /dev/null +++ b/prowler/providers/aws/services/inspector2/lib/vulnerabilities.py @@ -0,0 +1,8 @@ +MAX_LISTED_VULNERABILITIES = 10 + + +def summarize_vulnerabilities(vulnerabilities: list[str]) -> str: + """Join vulnerability identifiers, truncating long lists.""" + listed = ", ".join(vulnerabilities[:MAX_LISTED_VULNERABILITIES]) + remaining = len(vulnerabilities) - MAX_LISTED_VULNERABILITIES + return f"{listed} and {remaining} more" if remaining > 0 else listed diff --git a/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/__init__.py b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json new file mode 100644 index 0000000000..c1d8b48e20 --- /dev/null +++ b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.metadata.json @@ -0,0 +1,42 @@ +{ + "Provider": "aws", + "CheckID": "transfer_server_fips_security_policy_enabled", + "CheckTitle": "AWS Transfer Family server uses a FIPS security policy", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices" + ], + "ServiceName": "transfer", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "low", + "ResourceType": "AwsTransferServer", + "ResourceGroup": "network", + "Description": "**AWS Transfer Family servers** (SFTP, FTPS, AS2) are assessed for use of a **FIPS** security policy (`TransferSecurityPolicy-FIPS-*`, flagged `Fips: true` by AWS), which limits file-transfer sessions to the FIPS-enabled set of SSH and TLS algorithms.", + "Risk": "Servers without a FIPS security policy can negotiate algorithms outside the FIPS-enabled set, which does not meet requirements to protect federal or regulated files and credentials with **NIST CMVP validated cryptography**.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.aws.amazon.com/transfer/latest/userguide/security-policies.html", + "https://aws.amazon.com/compliance/fips/" + ], + "Remediation": { + "Code": { + "CLI": "aws transfer update-server --server-id --security-policy-name TransferSecurityPolicy-FIPS-2025-03", + "NativeIaC": "```yaml\nResources:\n :\n Type: AWS::Transfer::Server\n Properties:\n Protocols:\n - SFTP\n SecurityPolicyName: TransferSecurityPolicy-FIPS-2025-03 # FIX: FIPS security policy\n```", + "Other": "1. In the AWS Console, go to AWS Transfer Family > Servers\n2. Select the server and choose Edit on the Additional details panel\n3. Set Cryptographic algorithm options (Security policy) to a FIPS policy such as TransferSecurityPolicy-FIPS-2025-03\n4. Save the changes", + "Terraform": "```hcl\nresource \"aws_transfer_server\" \"\" {\n protocols = [\"SFTP\"]\n security_policy_name = \"TransferSecurityPolicy-FIPS-2025-03\" # FIX: FIPS security policy\n}\n```" + }, + "Recommendation": { + "Text": "Use a **FIPS** security policy, such as `TransferSecurityPolicy-FIPS-2025-03`, on every Transfer Family server that exchanges federal or regulated data.", + "Url": "https://hub.prowler.com/check/transfer_server_fips_security_policy_enabled" + } + }, + "Categories": [ + "encryption" + ], + "DependsOn": [], + "RelatedTo": [ + "transfer_server_in_transit_encryption_enabled", + "transfer_server_pqc_ssh_kex_enabled" + ], + "Notes": "" +} diff --git a/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py new file mode 100644 index 0000000000..99d86097ba --- /dev/null +++ b/prowler/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled.py @@ -0,0 +1,38 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.transfer.transfer_client import transfer_client + + +class transfer_server_fips_security_policy_enabled(Check): + """Ensure every AWS Transfer Family server uses a FIPS security policy.""" + + def execute(self) -> list[Check_Report_AWS]: + """Report whether each Transfer Family server uses a FIPS security policy.""" + findings = [] + unretrieved_servers = [] + for server in transfer_client.servers.values(): + policy = server.security_policy_name + if not policy: + unretrieved_servers.append(server.id) + continue + report = Check_Report_AWS(metadata=self.metadata(), resource=server) + if "FIPS" in policy.split("-"): + report.status = "PASS" + report.status_extended = ( + f"Transfer Server {server.id} uses FIPS security policy {policy}." + ) + else: + report.status = "FAIL" + report.status_extended = f"Transfer Server {server.id} uses security policy {policy}, which is not a FIPS security policy." + findings.append(report) + if unretrieved_servers: + report = Check_Report_AWS(metadata=self.metadata(), resource={}) + report.resource_id = transfer_client.audited_account + report.resource_arn = transfer_client.audited_account_arn + report.region = transfer_client.region + report.status = "MANUAL" + report.status_extended = ( + "Transfer Server security policies could not be retrieved for " + f"{', '.join(unretrieved_servers)}; verify the transfer:DescribeServer permission." + ) + findings.append(report) + return findings diff --git a/tests/config/config_test.py b/tests/config/config_test.py index fbff8ade29..4d469ef009 100644 --- a/tests/config/config_test.py +++ b/tests/config/config_test.py @@ -138,6 +138,8 @@ config_aws = { "organizations_enabled_regions": [], "organizations_trusted_delegated_administrators": [], "ecr_repository_vulnerability_minimum_severity": "MEDIUM", + "inspector2_max_days_since_last_scan": 3, + "inspector2_active_finding_max_age_days": 192, "verify_premium_support_plans": True, "threat_detection_privilege_escalation_threshold": 0.2, "threat_detection_privilege_escalation_minutes": 1440, diff --git a/tests/config/fixtures/config.yaml b/tests/config/fixtures/config.yaml index a64e497544..8b02ba2d43 100644 --- a/tests/config/fixtures/config.yaml +++ b/tests/config/fixtures/config.yaml @@ -139,6 +139,14 @@ aws: # MEDIUM ecr_repository_vulnerability_minimum_severity: "MEDIUM" + # AWS Inspector2 + # aws.inspector2_coverage_recently_scanned + # Maximum days since Inspector2 last scanned an actively covered resource + inspector2_max_days_since_last_scan: 3 + # aws.inspector2_active_findings_within_max_age + # Maximum days an Inspector2 finding can stay active since it was first observed + inspector2_active_finding_max_age_days: 192 + # AWS Trusted Advisor # aws.trustedadvisor_premium_support_plan_subscribed verify_premium_support_plans: True diff --git a/tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py b/tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py new file mode 100644 index 0000000000..ee1afde340 --- /dev/null +++ b/tests/providers/aws/services/elbv2/elbv2_listener_fips_tls_enabled/elbv2_listener_fips_tls_enabled_test.py @@ -0,0 +1,156 @@ +from unittest import mock + +from boto3 import client, resource +from moto import mock_aws + +from tests.providers.aws.utils import ( + AWS_REGION_EU_WEST_1, + AWS_REGION_US_EAST_1, + set_mocked_aws_provider, +) + +CHECK_MODULE = "prowler.providers.aws.services.elbv2.elbv2_listener_fips_tls_enabled.elbv2_listener_fips_tls_enabled" +FIPS_POLICY = "ELBSecurityPolicy-TLS13-1-2-FIPS-2023-04" +NON_FIPS_POLICY = "ELBSecurityPolicy-TLS13-1-2-2021-06" + + +def create_application_load_balancer(): + conn = client("elbv2", region_name=AWS_REGION_EU_WEST_1) + ec2 = resource("ec2", region_name=AWS_REGION_EU_WEST_1) + security_group = ec2.create_security_group( + GroupName="a-security-group", Description="First One" + ) + vpc = ec2.create_vpc(CidrBlock="172.28.7.0/24", InstanceTenancy="default") + subnet1 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock="172.28.7.192/26", + AvailabilityZone=f"{AWS_REGION_EU_WEST_1}a", + ) + subnet2 = ec2.create_subnet( + VpcId=vpc.id, + CidrBlock="172.28.7.0/26", + AvailabilityZone=f"{AWS_REGION_EU_WEST_1}b", + ) + lb = conn.create_load_balancer( + Name="my-lb", + Subnets=[subnet1.id, subnet2.id], + SecurityGroups=[security_group.id], + Scheme="internal", + Type="application", + )["LoadBalancers"][0] + target_group_arn = conn.create_target_group( + Name="a-target", Protocol="HTTP", Port=8080, VpcId=vpc.id + )["TargetGroups"][0]["TargetGroupArn"] + return conn, lb, target_group_arn + + +def create_listener(conn, lb, target_group_arn, protocol, port, ssl_policy=None): + listener_args = { + "LoadBalancerArn": lb["LoadBalancerArn"], + "Protocol": protocol, + "Port": port, + "DefaultActions": [{"Type": "forward", "TargetGroupArn": target_group_arn}], + } + if ssl_policy: + listener_args["SslPolicy"] = ssl_policy + return conn.create_listener(**listener_args)["Listeners"][0] + + +def execute_check(service=None): + from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 + + aws_provider = set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1], + create_default_organization=False, + ) + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch(f"{CHECK_MODULE}.elbv2_client", new=service or ELBv2(aws_provider)), + ): + from prowler.providers.aws.services.elbv2.elbv2_listener_fips_tls_enabled.elbv2_listener_fips_tls_enabled import ( + elbv2_listener_fips_tls_enabled, + ) + + return elbv2_listener_fips_tls_enabled().execute() + + +class Test_elbv2_listener_fips_tls_enabled: + @mock_aws + def test_no_load_balancers(self): + assert execute_check() == [] + + @mock_aws + def test_http_listener_only(self): + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTP", 80) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].status_extended == "ELBv2 my-lb has no HTTPS/TLS listeners." + + @mock_aws + def test_fips_policy(self): + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTPS", 443, FIPS_POLICY) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == "ELBv2 my-lb has all HTTPS/TLS listeners using a FIPS TLS security policy." + ) + assert result[0].resource_id == "my-lb" + assert result[0].resource_arn == lb["LoadBalancerArn"] + assert result[0].region == AWS_REGION_EU_WEST_1 + + @mock_aws + def test_non_fips_policy(self): + conn, lb, target_group_arn = create_application_load_balancer() + listener = create_listener( + conn, lb, target_group_arn, "HTTPS", 443, NON_FIPS_POLICY + ) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"ELBv2 my-lb has HTTPS/TLS listeners without a FIPS TLS security policy: HTTPS:443 ({listener['ListenerArn']}) uses {NON_FIPS_POLICY}." + ) + + @mock_aws + def test_mixed_listeners(self): + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTPS", 443, FIPS_POLICY) + create_listener(conn, lb, target_group_arn, "HTTPS", 8443, NON_FIPS_POLICY) + + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert NON_FIPS_POLICY in result[0].status_extended + assert FIPS_POLICY not in result[0].status_extended + + @mock_aws + def test_listener_discovery_failed(self): + from prowler.providers.aws.services.elbv2.elbv2_service import ELBv2 + + conn, lb, target_group_arn = create_application_load_balancer() + create_listener(conn, lb, target_group_arn, "HTTPS", 443, NON_FIPS_POLICY) + service = ELBv2( + set_mocked_aws_provider( + [AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1], + create_default_organization=False, + ) + ) + service.loadbalancersv2[lb["LoadBalancerArn"]].listener_discovery_failed = True + + assert execute_check(service) == [] diff --git a/tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py b/tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py new file mode 100644 index 0000000000..bf57b346c2 --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_active_findings_kev_within_due_date/inspector2_active_findings_kev_within_due_date_test.py @@ -0,0 +1,136 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, + KnownExploitedVulnerability, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +FINDING_ARN = f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:finding/0e436649379db5f327e3cf5bb4421d76" +KEV_ID = "CVE-2024-3400" +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_active_findings_kev_within_due_date.inspector2_active_findings_kev_within_due_date" + + +def build_inspector(findings=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=findings, + ) + + +def build_finding(vulnerability_id=KEV_ID): + return Finding( + arn=FINDING_ARN, + type="PACKAGE_VULNERABILITY", + severity="CRITICAL", + first_observed_at=datetime.now(timezone.utc), + vulnerability_id=vulnerability_id, + resource_ids=["i-0123456789abcdef0"], + ) + + +def build_kev(date_due): + return KnownExploitedVulnerability( + id=KEV_ID, + date_added=datetime(2024, 4, 12, tzinfo=timezone.utc), + date_due=date_due, + ) + + +def execute_check(inspectors, known_exploited=None, lookup_failed=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.known_exploited_vulnerabilities = known_exploited or {} + inspector2_client.vulnerability_lookup_failed = lookup_failed or set() + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_active_findings_kev_within_due_date.inspector2_active_findings_kev_within_due_date import ( + inspector2_active_findings_kev_within_due_date, + ) + + return inspector2_active_findings_kev_within_due_date().execute() + + +class Test_inspector2_active_findings_kev_within_due_date: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(findings=[], status="DISABLED")]) == [] + + def test_kev_past_due_date(self): + result = execute_check( + [build_inspector(findings=[build_finding()])], + known_exploited={ + KEV_ID: build_kev(datetime(2024, 4, 19, tzinfo=timezone.utc)) + }, + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 has active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities past their remediation due date: {KEV_ID} (due 2024-04-19)." + ) + assert result[0].resource_id == "Inspector2" + assert result[0].resource_arn == INSPECTOR_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_kev_within_due_date(self): + result = execute_check( + [build_inspector(findings=[build_finding()])], + known_exploited={ + KEV_ID: build_kev(datetime.now(timezone.utc) + timedelta(days=7)) + }, + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 has no active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities past their remediation due date." + ) + + def test_no_kev_findings(self): + result = execute_check( + [build_inspector(findings=[build_finding("CVE-2022-40897")])] + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_kev_status_not_verified(self): + result = execute_check( + [build_inspector(findings=[build_finding()])], + lookup_failed={KEV_ID}, + ) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + + def test_findings_not_retrieved(self): + result = execute_check([build_inspector(findings=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" diff --git a/tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py b/tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py new file mode 100644 index 0000000000..288e7224ea --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_active_findings_no_known_exploited_vulnerabilities/inspector2_active_findings_no_known_exploited_vulnerabilities_test.py @@ -0,0 +1,149 @@ +from datetime import datetime, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, + KnownExploitedVulnerability, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +FINDING_ARN = f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:finding/0e436649379db5f327e3cf5bb4421d76" +KEV_ID = "CVE-2024-3400" +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_active_findings_no_known_exploited_vulnerabilities.inspector2_active_findings_no_known_exploited_vulnerabilities" + + +def build_inspector(findings=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=findings, + ) + + +def build_finding(vulnerability_id): + return Finding( + arn=FINDING_ARN, + type="PACKAGE_VULNERABILITY", + severity="CRITICAL", + first_observed_at=datetime.now(timezone.utc), + vulnerability_id=vulnerability_id, + resource_ids=["i-0123456789abcdef0"], + ) + + +def build_kev(vulnerability_id): + return KnownExploitedVulnerability( + id=vulnerability_id, + date_added=datetime(2024, 4, 12, tzinfo=timezone.utc), + date_due=datetime(2024, 4, 19, tzinfo=timezone.utc), + ) + + +def execute_check(inspectors, known_exploited=None, lookup_failed=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.known_exploited_vulnerabilities = known_exploited or {} + inspector2_client.vulnerability_lookup_failed = lookup_failed or set() + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_active_findings_no_known_exploited_vulnerabilities.inspector2_active_findings_no_known_exploited_vulnerabilities import ( + inspector2_active_findings_no_known_exploited_vulnerabilities, + ) + + return inspector2_active_findings_no_known_exploited_vulnerabilities().execute() + + +class Test_inspector2_active_findings_no_known_exploited_vulnerabilities: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(findings=[], status="DISABLED")]) == [] + + def test_no_kev_findings(self): + result = execute_check( + [build_inspector(findings=[build_finding("CVE-2022-40897")])] + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 has no active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities." + ) + assert result[0].resource_id == "Inspector2" + assert result[0].resource_arn == INSPECTOR_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_kev_finding(self): + result = execute_check( + [ + build_inspector( + findings=[build_finding(KEV_ID), build_finding("CVE-2022-40897")] + ) + ], + known_exploited={KEV_ID: build_kev(KEV_ID)}, + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 has active findings in region {AWS_REGION_EU_WEST_1} for CISA Known Exploited Vulnerabilities: {KEV_ID}." + ) + + def test_many_kev_findings_are_truncated(self): + vulnerability_ids = [f"CVE-2024-{number:04d}" for number in range(1, 13)] + result = execute_check( + [ + build_inspector( + findings=[build_finding(vid) for vid in vulnerability_ids] + ) + ], + known_exploited={vid: build_kev(vid) for vid in vulnerability_ids}, + ) + + assert result[0].status == "FAIL" + assert result[0].status_extended.endswith("CVE-2024-0010 and 2 more.") + + def test_kev_status_not_verified(self): + result = execute_check( + [build_inspector(findings=[build_finding(KEV_ID)])], + lookup_failed={KEV_ID}, + ) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Inspector2 could not verify the CISA Known Exploited Vulnerabilities status of {KEV_ID} in region {AWS_REGION_EU_WEST_1}; verify the inspector2:BatchGetFindingDetails permission." + ) + + def test_findings_not_retrieved(self): + result = execute_check([build_inspector(findings=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Inspector2 findings could not be retrieved in region {AWS_REGION_EU_WEST_1}; verify the inspector2:ListFindings permission." + ) diff --git a/tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py b/tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py new file mode 100644 index 0000000000..8b847c9014 --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_active_findings_within_max_age/inspector2_active_findings_within_max_age_test.py @@ -0,0 +1,140 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +FINDING_ARN = f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:finding/0e436649379db5f327e3cf5bb4421d76" +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_active_findings_within_max_age.inspector2_active_findings_within_max_age" + + +def build_inspector(findings=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=findings, + ) + + +def build_finding(age_days): + first_observed_at = ( + datetime.now(timezone.utc) - timedelta(days=age_days, hours=1) + if age_days is not None + else None + ) + return Finding( + arn=FINDING_ARN, + type="PACKAGE_VULNERABILITY", + severity="HIGH", + first_observed_at=first_observed_at, + vulnerability_id="CVE-2022-40897", + resource_ids=["i-0123456789abcdef0"], + ) + + +def execute_check(inspectors, audit_config=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.audit_config = audit_config or {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_active_findings_within_max_age.inspector2_active_findings_within_max_age import ( + inspector2_active_findings_within_max_age, + ) + + return inspector2_active_findings_within_max_age().execute() + + +class Test_inspector2_active_findings_within_max_age: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(findings=[], status="DISABLED")]) == [] + + def test_no_active_findings(self): + result = execute_check([build_inspector(findings=[])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 has no active findings in region {AWS_REGION_EU_WEST_1} first observed more than 192 days ago." + ) + assert result[0].resource_id == "Inspector2" + assert result[0].resource_arn == INSPECTOR_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_recent_findings(self): + result = execute_check([build_inspector(findings=[build_finding(30)])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_stale_findings(self): + result = execute_check( + [ + build_inspector( + findings=[ + build_finding(30), + build_finding(200), + build_finding(400), + ] + ) + ] + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 has 2 active findings in region {AWS_REGION_EU_WEST_1} first observed more than 192 days ago, the oldest 400 days ago." + ) + + def test_finding_just_over_max_age(self): + result = execute_check([build_inspector(findings=[build_finding(192)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + + def test_custom_max_age(self): + result = execute_check( + [build_inspector(findings=[build_finding(30)])], + audit_config={"inspector2_active_finding_max_age_days": 14}, + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + + def test_finding_without_first_observed_date_is_ignored(self): + result = execute_check([build_inspector(findings=[build_finding(None)])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_findings_not_retrieved(self): + result = execute_check([build_inspector(findings=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" diff --git a/tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py b/tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py new file mode 100644 index 0000000000..64d757feb2 --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_coverage_recently_scanned/inspector2_coverage_recently_scanned_test.py @@ -0,0 +1,170 @@ +from datetime import datetime, timedelta, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + CoveredResource, + Inspector, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +INSTANCE_ID = "i-0123456789abcdef0" +INSTANCE_ARN = ( + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" +) +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_coverage_recently_scanned.inspector2_coverage_recently_scanned" + + +def build_inspector(coverage=None, status="ENABLED"): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + coverage=coverage, + ) + + +def build_instance( + days_since_scan=None, scan_status_code="ACTIVE", scan_status_reason="SUCCESSFUL" +): + last_scanned_at = ( + datetime.now(timezone.utc) - timedelta(days=days_since_scan, hours=1) + if days_since_scan is not None + else None + ) + return CoveredResource( + id=INSTANCE_ID, + arn=INSTANCE_ARN, + region=AWS_REGION_EU_WEST_1, + resource_type="AWS_EC2_INSTANCE", + scan_type="PACKAGE", + scan_status_code=scan_status_code, + scan_status_reason=scan_status_reason, + last_scanned_at=last_scanned_at, + ) + + +def execute_check(inspectors, audit_config=None): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.audit_config = audit_config or {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_coverage_recently_scanned.inspector2_coverage_recently_scanned import ( + inspector2_coverage_recently_scanned, + ) + + return inspector2_coverage_recently_scanned().execute() + + +class Test_inspector2_coverage_recently_scanned: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(status="DISABLED", coverage=[])]) == [] + + def test_recently_scanned_resource(self): + result = execute_check([build_inspector(coverage=[build_instance(1)])]) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"AWS_EC2_INSTANCE {INSTANCE_ID} was last scanned by Inspector2 within the last 3 days." + ) + assert result[0].resource_id == INSTANCE_ID + assert result[0].resource_arn == INSTANCE_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_stale_resource(self): + result = execute_check([build_inspector(coverage=[build_instance(10)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"AWS_EC2_INSTANCE {INSTANCE_ID} was last scanned by Inspector2 more than 3 days ago." + ) + + def test_resource_scanned_just_over_max_days(self): + result = execute_check([build_inspector(coverage=[build_instance(3)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + + def test_custom_max_days(self): + result = execute_check( + [build_inspector(coverage=[build_instance(10)])], + audit_config={"inspector2_max_days_since_last_scan": 14}, + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + + def test_resource_without_recorded_scan(self): + result = execute_check([build_inspector(coverage=[build_instance(None)])]) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"AWS_EC2_INSTANCE {INSTANCE_ID} has no recorded Inspector2 scan." + ) + + def test_pending_initial_scan_is_skipped(self): + assert ( + execute_check( + [ + build_inspector( + coverage=[ + build_instance( + None, scan_status_reason="PENDING_INITIAL_SCAN" + ) + ] + ) + ] + ) + == [] + ) + + def test_inactive_resource_is_skipped(self): + assert ( + execute_check( + [ + build_inspector( + coverage=[ + build_instance( + 10, + scan_status_code="INACTIVE", + scan_status_reason="NO_INVENTORY", + ) + ] + ) + ] + ) + == [] + ) + + def test_coverage_not_retrieved(self): + result = execute_check([build_inspector(coverage=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert result[0].resource_arn == INSPECTOR_ARN diff --git a/tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py b/tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py new file mode 100644 index 0000000000..1ce2e21c4a --- /dev/null +++ b/tests/providers/aws/services/inspector2/inspector2_coverage_scan_status_active/inspector2_coverage_scan_status_active_test.py @@ -0,0 +1,132 @@ +from datetime import datetime, timezone +from unittest import mock + +from prowler.providers.aws.services.inspector2.inspector2_service import ( + CoveredResource, + Inspector, +) +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_EU_WEST_1, + set_mocked_aws_provider, +) + +INSPECTOR_ARN = ( + f"arn:aws:inspector2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:inspector2" +) +INSTANCE_ID = "i-0123456789abcdef0" +INSTANCE_ARN = ( + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" +) +CHECK_MODULE = "prowler.providers.aws.services.inspector2.inspector2_coverage_scan_status_active.inspector2_coverage_scan_status_active" + + +def build_inspector(status="ENABLED", coverage=None): + return Inspector( + id="Inspector2", + arn=INSPECTOR_ARN, + region=AWS_REGION_EU_WEST_1, + status=status, + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + coverage=coverage, + ) + + +def build_instance(scan_status_code, scan_status_reason): + return CoveredResource( + id=INSTANCE_ID, + arn=INSTANCE_ARN, + region=AWS_REGION_EU_WEST_1, + resource_type="AWS_EC2_INSTANCE", + scan_type="PACKAGE", + scan_status_code=scan_status_code, + scan_status_reason=scan_status_reason, + last_scanned_at=datetime.now(timezone.utc), + ) + + +def execute_check(inspectors): + inspector2_client = mock.MagicMock() + inspector2_client.inspectors = inspectors + inspector2_client.audit_config = {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_aws_provider([AWS_REGION_EU_WEST_1]), + ), + mock.patch(f"{CHECK_MODULE}.inspector2_client", new=inspector2_client), + ): + from prowler.providers.aws.services.inspector2.inspector2_coverage_scan_status_active.inspector2_coverage_scan_status_active import ( + inspector2_coverage_scan_status_active, + ) + + return inspector2_coverage_scan_status_active().execute() + + +class Test_inspector2_coverage_scan_status_active: + def test_no_resources(self): + assert execute_check([]) == [] + + def test_inspector_disabled(self): + assert execute_check([build_inspector(status="DISABLED", coverage=[])]) == [] + + def test_no_covered_resources(self): + assert execute_check([build_inspector(coverage=[])]) == [] + + def test_active_resource(self): + result = execute_check( + [build_inspector(coverage=[build_instance("ACTIVE", "SUCCESSFUL")])] + ) + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Inspector2 is actively scanning AWS_EC2_INSTANCE {INSTANCE_ID}." + ) + assert result[0].resource_id == INSTANCE_ID + assert result[0].resource_arn == INSTANCE_ARN + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_inactive_resource(self): + result = execute_check( + [ + build_inspector( + coverage=[build_instance("INACTIVE", "UNMANAGED_EC2_INSTANCE")] + ) + ] + ) + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Inspector2 is not scanning AWS_EC2_INSTANCE {INSTANCE_ID}: UNMANAGED_EC2_INSTANCE." + ) + assert result[0].resource_id == INSTANCE_ID + + def test_not_applicable_resource_is_skipped(self): + assert ( + execute_check( + [ + build_inspector( + coverage=[build_instance("INACTIVE", "EC2_INSTANCE_STOPPED")] + ) + ] + ) + == [] + ) + + def test_coverage_not_retrieved(self): + result = execute_check([build_inspector(coverage=None)]) + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Inspector2 coverage could not be retrieved in region {AWS_REGION_EU_WEST_1}; verify the inspector2:ListCoverage permission." + ) + assert result[0].resource_arn == INSPECTOR_ARN diff --git a/tests/providers/aws/services/inspector2/inspector2_service_test.py b/tests/providers/aws/services/inspector2/inspector2_service_test.py index c84797eacd..7695e889eb 100644 --- a/tests/providers/aws/services/inspector2/inspector2_service_test.py +++ b/tests/providers/aws/services/inspector2/inspector2_service_test.py @@ -1,18 +1,30 @@ -from datetime import datetime +from datetime import datetime, timezone from unittest.mock import patch import botocore +from botocore.exceptions import ClientError -from prowler.providers.aws.services.inspector2.inspector2_service import Inspector2 +from prowler.providers.aws.services.inspector2.inspector2_service import ( + Finding, + Inspector, + Inspector2, +) from tests.providers.aws.utils import ( AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1, + AWS_REGION_US_EAST_1, set_mocked_aws_provider, ) FINDING_ARN = ( "arn:aws:inspector2:us-east-1:123456789012:finding/0e436649379db5f327e3cf5bb4421d76" ) +VULNERABILITY_ID = "CVE-2022-40897" +INSTANCE_ID = "i-0123456789abcdef0" +FIRST_OBSERVED_AT = datetime(2024, 1, 1, tzinfo=timezone.utc) +LAST_SCANNED_AT = datetime(2024, 6, 1, tzinfo=timezone.utc) +KEV_DATE_ADDED = datetime(2024, 4, 12, tzinfo=timezone.utc) +KEV_DATE_DUE = datetime(2024, 5, 3, tzinfo=timezone.utc) # Mocking Calls make_api_call = botocore.client.BaseClient._make_api_call @@ -64,16 +76,83 @@ def mock_make_api_call(self, operation_name, kwargs): "description": "Finding Description", "severity": "MEDIUM", "status": "ACTIVE", - "title": "CVE-2022-40897 - setuptools", + "title": f"{VULNERABILITY_ID} - setuptools", "type": "PACKAGE_VULNERABILITY", + "firstObservedAt": FIRST_OBSERVED_AT, "updatedAt": datetime(2024, 1, 1), + "packageVulnerabilityDetails": { + "vulnerabilityId": VULNERABILITY_ID + }, + "resources": [{"id": INSTANCE_ID, "type": "AWS_EC2_INSTANCE"}], } ] } + if operation_name == "ListCoverage": + return { + "coveredResources": [ + { + "resourceId": INSTANCE_ID, + "resourceType": "AWS_EC2_INSTANCE", + "accountId": AWS_ACCOUNT_NUMBER, + "scanType": "PACKAGE", + "scanStatus": {"statusCode": "ACTIVE", "reason": "SUCCESSFUL"}, + "lastScannedAt": LAST_SCANNED_AT, + } + ] + } + if operation_name == "BatchGetFindingDetails": + return { + "findingDetails": [ + { + "findingArn": FINDING_ARN, + "cisaData": { + "dateAdded": KEV_DATE_ADDED, + "dateDue": KEV_DATE_DUE, + }, + } + ], + "errors": [], + } return make_api_call(self, operation_name, kwargs) +def mock_make_api_call_finding_details_denied(self, operation_name, kwargs): + if operation_name == "BatchGetFindingDetails": + raise ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "denied"}}, + operation_name, + ) + return mock_make_api_call(self, operation_name, kwargs) + + +def mock_finding_details_error(error_code): + def _mock(self, operation_name, kwargs): + if operation_name == "BatchGetFindingDetails": + return { + "findingDetails": [], + "errors": [ + { + "findingArn": FINDING_ARN, + "errorCode": error_code, + "errorMessage": "error", + } + ], + } + return mock_make_api_call(self, operation_name, kwargs) + + return _mock + + +def mock_make_api_call_list_denied(self, operation_name, kwargs): + if operation_name in ("ListFindings", "ListCoverage"): + raise ClientError( + {"Error": {"Code": "AccessDeniedException", "Message": "denied"}}, + operation_name, + ) + return mock_make_api_call(self, operation_name, kwargs) + + def mock_generate_regional_clients(provider, service): regional_client = provider._session.current_session.client( service, region_name=AWS_REGION_EU_WEST_1 @@ -82,6 +161,29 @@ def mock_generate_regional_clients(provider, service): return {AWS_REGION_EU_WEST_1: regional_client} +def build_inspector(region, vulnerability_ids): + return Inspector( + id="Inspector2", + arn=f"arn:aws:inspector2:{region}:{AWS_ACCOUNT_NUMBER}:inspector2", + region=region, + status="ENABLED", + ec2_status="ENABLED", + ecr_status="ENABLED", + lambda_status="ENABLED", + lambda_code_status="ENABLED", + findings=[ + Finding( + arn=f"arn:aws:inspector2:{region}:{AWS_ACCOUNT_NUMBER}:finding/{index}", + type="PACKAGE_VULNERABILITY", + severity="HIGH", + first_observed_at=FIRST_OBSERVED_AT, + vulnerability_id=vulnerability_id, + ) + for index, vulnerability_id in enumerate(vulnerability_ids) + ], + ) + + # Patch every AWS call using Boto3 and generate_regional_clients to have 1 client @patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call) @patch( @@ -118,3 +220,115 @@ class Test_Inspector2_Service: aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) inspector2 = Inspector2(aws_provider) assert inspector2.inspectors[0].active_findings + + def test_list_findings(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + findings = inspector2.inspectors[0].findings + assert len(findings) == 1 + assert findings[0].arn == FINDING_ARN + assert findings[0].type == "PACKAGE_VULNERABILITY" + assert findings[0].severity == "MEDIUM" + assert findings[0].first_observed_at == FIRST_OBSERVED_AT + assert findings[0].vulnerability_id == VULNERABILITY_ID + assert findings[0].resource_ids == [INSTANCE_ID] + + def test_list_coverage(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + coverage = inspector2.inspectors[0].coverage + assert len(coverage) == 1 + assert coverage[0].id == INSTANCE_ID + assert ( + coverage[0].arn + == f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" + ) + assert coverage[0].region == AWS_REGION_EU_WEST_1 + assert coverage[0].resource_type == "AWS_EC2_INSTANCE" + assert coverage[0].scan_type == "PACKAGE" + assert coverage[0].scan_status_code == "ACTIVE" + assert coverage[0].scan_status_reason == "SUCCESSFUL" + assert coverage[0].last_scanned_at == LAST_SCANNED_AT + + def test_list_coverage_keeps_audited_resources(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + aws_provider._audit_resources = [ + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/{INSTANCE_ID}" + ] + inspector2 = Inspector2(aws_provider) + assert len(inspector2.inspectors[0].coverage) == 1 + + def test_list_coverage_skips_non_audited_resources(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + aws_provider._audit_resources = [ + f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:instance/i-0fedcba9876543210" + ] + inspector2 = Inspector2(aws_provider) + assert inspector2.inspectors[0].coverage == [] + + def test_batch_get_finding_details(self): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + known_exploited = inspector2.known_exploited_vulnerabilities[VULNERABILITY_ID] + assert known_exploited.id == VULNERABILITY_ID + assert known_exploited.date_added == KEV_DATE_ADDED + assert known_exploited.date_due == KEV_DATE_DUE + assert inspector2.vulnerability_lookup_failed == set() + + def test_batch_get_finding_details_denied(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_make_api_call_finding_details_denied, + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.known_exploited_vulnerabilities == {} + assert inspector2.vulnerability_lookup_failed == {VULNERABILITY_ID} + + def test_finding_details_not_found_is_not_a_lookup_failure(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_finding_details_error("FINDING_DETAILS_NOT_FOUND"), + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.known_exploited_vulnerabilities == {} + assert inspector2.vulnerability_lookup_failed == set() + + def test_finding_details_error_is_a_lookup_failure(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_finding_details_error("INTERNAL_ERROR"), + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.known_exploited_vulnerabilities == {} + assert inspector2.vulnerability_lookup_failed == {VULNERABILITY_ID} + + def test_list_findings_and_coverage_denied(self): + with patch( + "botocore.client.BaseClient._make_api_call", + new=mock_make_api_call_list_denied, + ): + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + inspector2 = Inspector2(aws_provider) + assert inspector2.inspectors[0].findings is None + assert inspector2.inspectors[0].coverage is None + assert inspector2.known_exploited_vulnerabilities == {} + + def test_finding_detail_batches_use_one_finding_per_cve(self): + vulnerability_ids = [f"CVE-2024-{number:04d}" for number in range(25)] + batches = Inspector2._get_finding_detail_batches( + [ + build_inspector( + AWS_REGION_EU_WEST_1, + vulnerability_ids + vulnerability_ids[:5] + ["GHSA-xxxx-yyyy-zzzz"], + ), + build_inspector(AWS_REGION_US_EAST_1, vulnerability_ids[:3]), + ] + ) + assert [region for region, _ in batches] == [AWS_REGION_EU_WEST_1] * 3 + assert [len(findings) for _, findings in batches] == [10, 10, 5] + assert sorted(cve for _, findings in batches for _, cve in findings) == sorted( + vulnerability_ids + ) diff --git a/tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py b/tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py new file mode 100644 index 0000000000..c60add1918 --- /dev/null +++ b/tests/providers/aws/services/transfer/transfer_server_fips_security_policy_enabled/transfer_server_fips_security_policy_enabled_test.py @@ -0,0 +1,111 @@ +from unittest import mock +from unittest.mock import patch + +import botocore +from moto import mock_aws + +from tests.providers.aws.utils import ( + AWS_ACCOUNT_NUMBER, + AWS_REGION_US_EAST_1, + set_mocked_aws_provider, +) + +SERVER_ID = "s-01234567890abcdef" +SERVER_ARN = ( + f"arn:aws:transfer:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:server/{SERVER_ID}" +) +CHECK_MODULE = "prowler.providers.aws.services.transfer.transfer_server_fips_security_policy_enabled.transfer_server_fips_security_policy_enabled" + +make_api_call = botocore.client.BaseClient._make_api_call + + +def mock_server_with_policy(security_policy_name): + def _mock(self, operation_name, kwarg): + if operation_name == "ListServers": + return {"Servers": [{"Arn": SERVER_ARN, "ServerId": SERVER_ID}]} + if operation_name == "DescribeServer": + return { + "Server": { + "Arn": SERVER_ARN, + "ServerId": SERVER_ID, + "Protocols": ["SFTP"], + "SecurityPolicyName": security_policy_name, + } + } + return make_api_call(self, operation_name, kwarg) + + return _mock + + +def execute_check(): + from prowler.providers.aws.services.transfer.transfer_service import Transfer + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch(f"{CHECK_MODULE}.transfer_client", new=Transfer(aws_provider)), + ): + from prowler.providers.aws.services.transfer.transfer_server_fips_security_policy_enabled.transfer_server_fips_security_policy_enabled import ( + transfer_server_fips_security_policy_enabled, + ) + + return transfer_server_fips_security_policy_enabled().execute() + + +class Test_transfer_server_fips_security_policy_enabled: + @mock_aws + def test_no_servers(self): + assert execute_check() == [] + + @patch( + "botocore.client.BaseClient._make_api_call", + new=mock_server_with_policy("TransferSecurityPolicy-FIPS-2025-03"), + ) + @mock_aws + def test_fips_policy(self): + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Transfer Server {SERVER_ID} uses FIPS security policy TransferSecurityPolicy-FIPS-2025-03." + ) + assert result[0].resource_id == SERVER_ID + assert result[0].resource_arn == SERVER_ARN + assert result[0].region == AWS_REGION_US_EAST_1 + + @patch( + "botocore.client.BaseClient._make_api_call", + new=mock_server_with_policy("TransferSecurityPolicy-2024-01"), + ) + @mock_aws + def test_non_fips_policy(self): + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Transfer Server {SERVER_ID} uses security policy TransferSecurityPolicy-2024-01, which is not a FIPS security policy." + ) + + @patch( + "botocore.client.BaseClient._make_api_call", + new=mock_server_with_policy(""), + ) + @mock_aws + def test_policy_not_retrieved(self): + result = execute_check() + + assert len(result) == 1 + assert result[0].status == "MANUAL" + assert ( + result[0].status_extended + == f"Transfer Server security policies could not be retrieved for {SERVER_ID}; verify the transfer:DescribeServer permission." + ) + assert result[0].resource_id == AWS_ACCOUNT_NUMBER + assert result[0].region == AWS_REGION_US_EAST_1 From 682353e054fe98c0a4c57ae6baa2947e40654c7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Tue, 15 Sep 2026 09:44:32 +0200 Subject: [PATCH 59/77] fix(container): bump PowerShell to 7.5.11 in SDK and API (#12811) --- .trivyignore.yaml | 30 ------------------- Dockerfile | 6 ++-- api/Dockerfile | 6 ++-- ...pi-image-powershell-dotnet-cve.security.md | 1 + ...dk-image-powershell-dotnet-cve.security.md | 1 + 5 files changed, 8 insertions(+), 36 deletions(-) create mode 100644 api/changelog.d/api-image-powershell-dotnet-cve.security.md create mode 100644 prowler/changelog.d/sdk-image-powershell-dotnet-cve.security.md diff --git a/.trivyignore.yaml b/.trivyignore.yaml index 715c7b625e..efac339352 100644 --- a/.trivyignore.yaml +++ b/.trivyignore.yaml @@ -130,36 +130,6 @@ vulnerabilities: - "pkg:npm/ip-address" expired_at: 2027-01-31 - # CVE-2026-62901 is a DoS in System.Net.WebSockets (unchecked input for loop condition, - # CWE-606), fixed in .NET 9.0.19 / 10.0.11 (published 2026-08-11). The vulnerable runtime - # ships inside the PowerShell tarball the Dockerfile pins: 7.5.9 is the latest 7.5.x and - # bundles .NET 9.0.18; 7.6.4 bundles .NET 10.0.x < 10.0.11, so no published PowerShell - # release contains the fix yet. Prowler only invokes pwsh locally to run M365 module - # cmdlets; the image does not accept inbound WebSocket connections, so the DoS path is - # not reachable from the network. Remove this temporary suppression as soon as a - # PowerShell release shipping .NET 9.0.19+ is available. - - id: CVE-2026-62901 - purls: - - "pkg:nuget/Microsoft.NETCore.App.Runtime.linux-x64" - - "pkg:nuget/Microsoft.NETCore.App.Runtime.linux-arm64" - expired_at: 2026-09-15 - - # Modules compiled into the Trivy binary the images ship. The binary is pinned by version - # and verified by checksum in the Dockerfile; only a rebuild by its vendor moves these. - # CVE-2026-71556 affects go-git worktree operations that can follow symlinks outside a - # cloned repository. Trivy 0.73.0, the latest published release and the version the - # images ship, still pins that vulnerable version: - # https://github.com/aquasecurity/trivy/blob/v0.73.0/go.mod#L46 - # Trivy main already contains the 5.19.2 fix, but no published release includes it yet: - # https://github.com/aquasecurity/trivy/commit/a2edba9a03987ba0d2ebc8212c1a9a1e6979497b - # Prowler invokes Trivy only with `fs` on an existing local path or with `image`; it does - # not ask Trivy to clone or mutate a Git worktree, so the affected path is not reachable. - # Remove this temporary suppression as soon as a fixed Trivy release is available. - - id: CVE-2026-71556 - purls: - - "pkg:golang/github.com/go-git/go-git/v5" - expired_at: 2026-09-15 - # CVE-2026-84304 is a DoS in grpc-go <= 1.83.0: a peer fragments a gRPC stream into # millions of tiny HTTP/2 DATA frames until the receiver runs out of heap. Fixed in # 1.83.1 (published 2026-09-01). Trivy 0.74.0, the latest published release and the diff --git a/Dockerfile b/Dockerfile index 559b39c9eb..dc62fd64a6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ FROM python:3.12.13-slim-trixie@sha256:57cd7c3a7a273101a6485ba99423ee56815788280 LABEL maintainer="https://github.com/prowler-cloud/prowler" LABEL org.opencontainers.image.source="https://github.com/prowler-cloud/prowler" -ARG POWERSHELL_VERSION=7.5.9 +ARG POWERSHELL_VERSION=7.5.11 ENV POWERSHELL_VERSION=${POWERSHELL_VERSION} # Opt out of PowerShell telemetry (Application Insights -> dc.services.visualstudio.com) ENV POWERSHELL_TELEMETRY_OPTOUT=1 @@ -17,8 +17,8 @@ ENV ZIZMOR_VERSION=${ZIZMOR_VERSION} # Pinned here, not fetched with the artefact: a compromised release ships its own checksum. ARG TRIVY_SHA256_AMD64=2ae6fe3ee734b7fdf11335663e18c75ea12dccc76062f09f164a3b0f8be4371a ARG TRIVY_SHA256_ARM64=b94ce1976bbf3c15b514b605ee88be7c6d94a29be2302847ff01cb794d47aad5 -ARG POWERSHELL_SHA256_AMD64=492ff26bb958336bf61e597ce19e07648b4003bd2a08659e02f0e3e0446ebfe0 -ARG POWERSHELL_SHA256_ARM64=2503b71da3e83635592b092df59a0aca4c3606b4d9b068217bb00be989cb0d56 +ARG POWERSHELL_SHA256_AMD64=82a8b13d92b0f3ae48e56cf2f3f7961679371736ca90145ca71617c2913ba9d8 +ARG POWERSHELL_SHA256_ARM64=830ebda118c731ece3fa7e6b7e8573a21346387cbbca5b2f5e3b9bfe24f96672 ARG ZIZMOR_SHA256_AMD64=a8000f3c683319a523d3b20df0e75457ba591f049cfcbfa98966631b56733c03 ARG ZIZMOR_SHA256_ARM64=d66e37ef8a375fb07939c630ebf9709a6e0f20242bdc3faf672a7ed97e0b768d diff --git a/api/Dockerfile b/api/Dockerfile index ce5bccbb2c..2262bd00d6 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.12.13-slim-trixie@sha256:57cd7c3a7a273101a6485ba99423ee56815788280 LABEL maintainer="https://github.com/prowler-cloud/api" -ARG POWERSHELL_VERSION=7.5.9 +ARG POWERSHELL_VERSION=7.5.11 ENV POWERSHELL_VERSION=${POWERSHELL_VERSION} # Opt out of PowerShell telemetry (Application Insights -> dc.services.visualstudio.com) ENV POWERSHELL_TELEMETRY_OPTOUT=1 @@ -16,8 +16,8 @@ ENV ZIZMOR_VERSION=${ZIZMOR_VERSION} # Pinned here, not fetched with the artefact: a compromised release ships its own checksum. ARG TRIVY_SHA256_AMD64=2ae6fe3ee734b7fdf11335663e18c75ea12dccc76062f09f164a3b0f8be4371a ARG TRIVY_SHA256_ARM64=b94ce1976bbf3c15b514b605ee88be7c6d94a29be2302847ff01cb794d47aad5 -ARG POWERSHELL_SHA256_AMD64=492ff26bb958336bf61e597ce19e07648b4003bd2a08659e02f0e3e0446ebfe0 -ARG POWERSHELL_SHA256_ARM64=2503b71da3e83635592b092df59a0aca4c3606b4d9b068217bb00be989cb0d56 +ARG POWERSHELL_SHA256_AMD64=82a8b13d92b0f3ae48e56cf2f3f7961679371736ca90145ca71617c2913ba9d8 +ARG POWERSHELL_SHA256_ARM64=830ebda118c731ece3fa7e6b7e8573a21346387cbbca5b2f5e3b9bfe24f96672 ARG ZIZMOR_SHA256_AMD64=a8000f3c683319a523d3b20df0e75457ba591f049cfcbfa98966631b56733c03 ARG ZIZMOR_SHA256_ARM64=d66e37ef8a375fb07939c630ebf9709a6e0f20242bdc3faf672a7ed97e0b768d diff --git a/api/changelog.d/api-image-powershell-dotnet-cve.security.md b/api/changelog.d/api-image-powershell-dotnet-cve.security.md new file mode 100644 index 0000000000..28b91a32a0 --- /dev/null +++ b/api/changelog.d/api-image-powershell-dotnet-cve.security.md @@ -0,0 +1 @@ +PowerShell from 7.5.9 to 7.5.11 in the API container image, bundling .NET runtime 9.0.20 and patching CVE-2026-62901 diff --git a/prowler/changelog.d/sdk-image-powershell-dotnet-cve.security.md b/prowler/changelog.d/sdk-image-powershell-dotnet-cve.security.md new file mode 100644 index 0000000000..370aa37289 --- /dev/null +++ b/prowler/changelog.d/sdk-image-powershell-dotnet-cve.security.md @@ -0,0 +1 @@ +PowerShell from 7.5.9 to 7.5.11 in the SDK container image, bundling .NET runtime 9.0.20 and patching CVE-2026-62901 From 61ef44a03bb8842bf82e88e25e55931c24a8729d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Tue, 15 Sep 2026 09:56:50 +0200 Subject: [PATCH 60/77] fix(m365): skip defender preset policies without rules (#12809) --- ...5-defender-preset-policy-keyerror.fixed.md | 1 + ...defender_antiphishing_policy_configured.py | 6 ++ ...ispam_policy_inbound_no_allowed_domains.py | 6 ++ ...olicy_common_attachments_filter_enabled.py | 6 ++ ...omprehensive_attachments_filter_applied.py | 6 ++ ...ications_internal_users_malware_enabled.py | 6 ++ ...der_antiphishing_policy_configured_test.py | 83 +++++++++++++++++++ ..._policy_inbound_no_allowed_domains_test.py | 62 ++++++++++++++ ..._common_attachments_filter_enabled_test.py | 74 +++++++++++++++++ ...hensive_attachments_filter_applied_test.py | 74 +++++++++++++++++ ...ons_internal_users_malware_enabled_test.py | 76 +++++++++++++++++ 11 files changed, 400 insertions(+) create mode 100644 prowler/changelog.d/m365-defender-preset-policy-keyerror.fixed.md diff --git a/prowler/changelog.d/m365-defender-preset-policy-keyerror.fixed.md b/prowler/changelog.d/m365-defender-preset-policy-keyerror.fixed.md new file mode 100644 index 0000000000..2a50037e84 --- /dev/null +++ b/prowler/changelog.d/m365-defender-preset-policy-keyerror.fixed.md @@ -0,0 +1 @@ +`KeyError` in M365 Defender malware, anti-phishing and inbound anti-spam checks when the tenant has Standard or Strict preset security policies diff --git a/prowler/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured.py b/prowler/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured.py index 61727b9d3c..5c467f941a 100644 --- a/prowler/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured.py +++ b/prowler/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured.py @@ -55,6 +55,12 @@ class defender_antiphishing_policy_configured(Check): policy_name, policy, ) in defender_client.antiphishing_policies.items(): + # Preset security policies are scoped by protection policy rules, not filter rules + if ( + not policy.default + and policy.name not in defender_client.antiphishing_rules + ): + continue report = CheckReportM365( metadata=self.metadata(), resource=policy, diff --git a/prowler/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains.py b/prowler/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains.py index 67b6643e9e..56616258e0 100644 --- a/prowler/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains.py +++ b/prowler/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains.py @@ -51,6 +51,12 @@ class defender_antispam_policy_inbound_no_allowed_domains(Check): default_policy_well_configured = False for policy in defender_client.inbound_spam_policies: + # Preset security policies are scoped by protection policy rules, not filter rules + if ( + not policy.default + and policy.identity not in defender_client.inbound_spam_rules + ): + continue report = CheckReportM365( metadata=self.metadata(), resource=policy, diff --git a/prowler/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled.py b/prowler/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled.py index a0b817cda3..d9a7080295 100644 --- a/prowler/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled.py +++ b/prowler/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled.py @@ -51,6 +51,12 @@ class defender_malware_policy_common_attachments_filter_enabled(Check): default_policy_well_configured = False for policy in defender_client.malware_policies: + # Preset security policies are scoped by protection policy rules, not filter rules + if ( + not policy.is_default + and policy.identity not in defender_client.malware_rules + ): + continue report = CheckReportM365( metadata=self.metadata(), resource=policy, diff --git a/prowler/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied.py b/prowler/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied.py index 87aa4ab50e..808ece11b9 100644 --- a/prowler/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied.py +++ b/prowler/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied.py @@ -114,6 +114,12 @@ class defender_malware_policy_comprehensive_attachments_filter_applied(Check): default_policy_well_configured = False for policy in defender_client.malware_policies: + # Preset security policies are scoped by protection policy rules, not filter rules + if ( + not policy.is_default + and policy.identity not in defender_client.malware_rules + ): + continue report = CheckReportM365( metadata=self.metadata(), resource=policy, diff --git a/prowler/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled.py b/prowler/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled.py index 735cc6b9e9..ab5efc8efe 100644 --- a/prowler/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled.py +++ b/prowler/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled.py @@ -51,6 +51,12 @@ class defender_malware_policy_notifications_internal_users_malware_enabled(Check default_policy_well_configured = False for policy in defender_client.malware_policies: + # Preset security policies are scoped by protection policy rules, not filter rules + if ( + not policy.is_default + and policy.identity not in defender_client.malware_rules + ): + continue report = CheckReportM365( metadata=self.metadata(), resource=policy, diff --git a/tests/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured_test.py b/tests/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured_test.py index 8610e96769..984fa648df 100644 --- a/tests/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured_test.py +++ b/tests/providers/m365/services/defender/defender_antiphishing_policy_configured/defender_antiphishing_policy_configured_test.py @@ -521,3 +521,86 @@ class Test_defender_antiphishing_policy_configured: check = defender_antiphishing_policy_configured() result = check.execute() assert len(result) == 0 + + def test_preset_policy_without_rule_is_skipped(self): + defender_client = mock.MagicMock() + defender_client.audited_tenant = "audited_tenant" + defender_client.audited_domain = DOMAIN + defender_client.audit_config = {} + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.defender.defender_antiphishing_policy_configured.defender_antiphishing_policy_configured.defender_client", + new=defender_client, + ), + ): + from prowler.providers.m365.services.defender.defender_antiphishing_policy_configured.defender_antiphishing_policy_configured import ( + defender_antiphishing_policy_configured, + ) + from prowler.providers.m365.services.defender.defender_service import ( + AntiphishingPolicy, + AntiphishingRule, + ) + + defender_client.antiphishing_policies = { + "Default": AntiphishingPolicy( + name="Default", + spoof_intelligence=True, + spoof_intelligence_action="Quarantine", + dmarc_reject_action="Quarantine", + dmarc_quarantine_action="Quarantine", + safety_tips=True, + unauthenticated_sender_action=True, + show_tag=True, + honor_dmarc_policy=True, + default=True, + ), + "Standard Preset Security Policy1663355404982": AntiphishingPolicy( + name="Standard Preset Security Policy1663355404982", + spoof_intelligence=True, + spoof_intelligence_action="Quarantine", + dmarc_reject_action="Quarantine", + dmarc_quarantine_action="Quarantine", + safety_tips=True, + unauthenticated_sender_action=True, + show_tag=True, + honor_dmarc_policy=True, + default=False, + ), + "Custom1": AntiphishingPolicy( + name="Custom1", + spoof_intelligence=True, + spoof_intelligence_action="Quarantine", + dmarc_reject_action="Quarantine", + dmarc_quarantine_action="Quarantine", + safety_tips=True, + unauthenticated_sender_action=True, + show_tag=True, + honor_dmarc_policy=True, + default=False, + ), + } + defender_client.antiphishing_rules = { + "Custom1": AntiphishingRule( + state="Enabled", + priority=1, + users=["user1@example.com"], + groups=None, + domains=None, + ) + } + + check = defender_antiphishing_policy_configured() + result = check.execute() + + assert len(result) == 2 + assert "Standard Preset Security Policy1663355404982" not in [ + finding.resource_id for finding in result + ] diff --git a/tests/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains_test.py b/tests/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains_test.py index 625fc8ded3..4e0a5482a1 100644 --- a/tests/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains_test.py +++ b/tests/providers/m365/services/defender/defender_antispam_policy_inbound_no_allowed_domains/defender_antispam_policy_inbound_no_allowed_domains_test.py @@ -410,3 +410,65 @@ class Test_defender_antispam_policy_inbound_no_allowed_domains: check = defender_antispam_policy_inbound_no_allowed_domains() result = check.execute() assert len(result) == 0 + + def test_preset_policy_without_rule_is_skipped(self): + defender_client = mock.MagicMock() + defender_client.audited_tenant = "audited_tenant" + defender_client.audited_domain = DOMAIN + defender_client.audit_config = {} + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.defender.defender_antispam_policy_inbound_no_allowed_domains.defender_antispam_policy_inbound_no_allowed_domains.defender_client", + new=defender_client, + ), + ): + from prowler.providers.m365.services.defender.defender_antispam_policy_inbound_no_allowed_domains.defender_antispam_policy_inbound_no_allowed_domains import ( + defender_antispam_policy_inbound_no_allowed_domains, + ) + from prowler.providers.m365.services.defender.defender_service import ( + DefenderInboundSpamPolicy, + InboundSpamRule, + ) + + defender_client.inbound_spam_policies = [ + DefenderInboundSpamPolicy( + identity="Default", + allowed_sender_domains=[], + default=True, + ), + DefenderInboundSpamPolicy( + identity="Standard Preset Security Policy1663355404982", + allowed_sender_domains=[], + default=False, + ), + DefenderInboundSpamPolicy( + identity="Custom1", + allowed_sender_domains=[], + default=False, + ), + ] + defender_client.inbound_spam_rules = { + "Custom1": InboundSpamRule( + state="Enabled", + priority=1, + users=["user1@example.com"], + groups=None, + domains=None, + ) + } + + check = defender_antispam_policy_inbound_no_allowed_domains() + result = check.execute() + + assert len(result) == 2 + assert "Standard Preset Security Policy1663355404982" not in [ + finding.resource_id for finding in result + ] diff --git a/tests/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled_test.py b/tests/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled_test.py index adb62b213d..f2b9fdb402 100644 --- a/tests/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled_test.py +++ b/tests/providers/m365/services/defender/defender_malware_policy_common_attachments_filter_enabled/defender_malware_policy_common_attachments_filter_enabled_test.py @@ -442,3 +442,77 @@ class Test_defender_malware_policy_common_attachments_filter_enabled: check = defender_malware_policy_common_attachments_filter_enabled() result = check.execute() assert len(result) == 0 + + def test_preset_policy_without_rule_is_skipped(self): + defender_client = mock.MagicMock() + defender_client.audited_tenant = "audited_tenant" + defender_client.audited_domain = DOMAIN + defender_client.audit_config = {} + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.defender.defender_malware_policy_common_attachments_filter_enabled.defender_malware_policy_common_attachments_filter_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.m365.services.defender.defender_malware_policy_common_attachments_filter_enabled.defender_malware_policy_common_attachments_filter_enabled import ( + defender_malware_policy_common_attachments_filter_enabled, + ) + from prowler.providers.m365.services.defender.defender_service import ( + MalwarePolicy, + MalwareRule, + ) + + defender_client.audit_config = { + "recommended_blocked_file_types": ["exe", "bat"] + } + defender_client.malware_policies = [ + MalwarePolicy( + identity="Default", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=True, + ), + MalwarePolicy( + identity="Standard Preset Security Policy1663355404982", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=False, + ), + MalwarePolicy( + identity="Custom1", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=False, + ), + ] + defender_client.malware_rules = { + "Custom1": MalwareRule( + state="Enabled", + priority=1, + users=["user1@example.com"], + groups=None, + domains=None, + ) + } + + check = defender_malware_policy_common_attachments_filter_enabled() + result = check.execute() + + assert len(result) == 2 + assert "Standard Preset Security Policy1663355404982" not in [ + finding.resource_id for finding in result + ] diff --git a/tests/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied_test.py b/tests/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied_test.py index 682f86c768..7a9cfbbd90 100644 --- a/tests/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied_test.py +++ b/tests/providers/m365/services/defender/defender_malware_policy_comprehensive_attachments_filter_applied/defender_malware_policy_comprehensive_attachments_filter_applied_test.py @@ -452,3 +452,77 @@ class Test_defender_malware_policy_comprehensive_attachments_filter_applied: check = defender_malware_policy_comprehensive_attachments_filter_applied() result = check.execute() assert len(result) == 0 + + def test_preset_policy_without_rule_is_skipped(self): + defender_client = mock.MagicMock() + defender_client.audited_tenant = "audited_tenant" + defender_client.audited_domain = DOMAIN + defender_client.audit_config = {} + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.defender.defender_malware_policy_comprehensive_attachments_filter_applied.defender_malware_policy_comprehensive_attachments_filter_applied.defender_client", + new=defender_client, + ), + ): + from prowler.providers.m365.services.defender.defender_malware_policy_comprehensive_attachments_filter_applied.defender_malware_policy_comprehensive_attachments_filter_applied import ( + defender_malware_policy_comprehensive_attachments_filter_applied, + ) + from prowler.providers.m365.services.defender.defender_service import ( + MalwarePolicy, + MalwareRule, + ) + + defender_client.audit_config = { + "recommended_blocked_file_types": ["exe", "bat"] + } + defender_client.malware_policies = [ + MalwarePolicy( + identity="Default", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=True, + ), + MalwarePolicy( + identity="Standard Preset Security Policy1663355404982", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=False, + ), + MalwarePolicy( + identity="Custom1", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=False, + ), + ] + defender_client.malware_rules = { + "Custom1": MalwareRule( + state="Enabled", + priority=1, + users=["user1@example.com"], + groups=None, + domains=None, + ) + } + + check = defender_malware_policy_comprehensive_attachments_filter_applied() + result = check.execute() + + assert len(result) == 2 + assert "Standard Preset Security Policy1663355404982" not in [ + finding.resource_id for finding in result + ] diff --git a/tests/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled_test.py b/tests/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled_test.py index 16fe656c2b..7764da21e4 100644 --- a/tests/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled_test.py +++ b/tests/providers/m365/services/defender/defender_malware_policy_notifications_internal_users_malware_enabled/defender_malware_policy_notifications_internal_users_malware_enabled_test.py @@ -456,3 +456,79 @@ class Test_defender_malware_policy_notifications_internal_users_malware_enabled: ) result = check.execute() assert len(result) == 0 + + def test_preset_policy_without_rule_is_skipped(self): + defender_client = mock.MagicMock() + defender_client.audited_tenant = "audited_tenant" + defender_client.audited_domain = DOMAIN + defender_client.audit_config = {} + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_m365_provider(), + ), + mock.patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online" + ), + mock.patch( + "prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import ( + defender_malware_policy_notifications_internal_users_malware_enabled, + ) + from prowler.providers.m365.services.defender.defender_service import ( + MalwarePolicy, + MalwareRule, + ) + + defender_client.audit_config = { + "recommended_blocked_file_types": ["exe", "bat"] + } + defender_client.malware_policies = [ + MalwarePolicy( + identity="Default", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=True, + ), + MalwarePolicy( + identity="Standard Preset Security Policy1663355404982", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=False, + ), + MalwarePolicy( + identity="Custom1", + enable_file_filter=True, + enable_internal_sender_admin_notifications=True, + internal_sender_admin_address="admin@example.com", + file_types=["exe", "bat"], + is_default=False, + ), + ] + defender_client.malware_rules = { + "Custom1": MalwareRule( + state="Enabled", + priority=1, + users=["user1@example.com"], + groups=None, + domains=None, + ) + } + + check = ( + defender_malware_policy_notifications_internal_users_malware_enabled() + ) + result = check.execute() + + assert len(result) == 2 + assert "Standard Preset Security Policy1663355404982" not in [ + finding.resource_id for finding in result + ] From c0fdd5bdf37d6cd82f23b434af62a035ee3e64b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Tue, 15 Sep 2026 11:07:31 +0200 Subject: [PATCH 61/77] fix(ui): add FedRAMP 20x cross-provider mappers (#12810) Co-authored-by: alejandrobailo --- ...ramp-20x-cross-provider-breakdown.fixed.md | 1 + .../fedramp-20x-details.tsx | 89 +++++++++ ui/lib/compliance/c5.tsx | 10 +- ui/lib/compliance/cis-controls.tsx | 10 +- ui/lib/compliance/{cmmc.tsx => cmmc.ts} | 70 +------ ui/lib/compliance/commons.tsx | 11 +- ui/lib/compliance/compliance-mapper.test.ts | 11 ++ ui/lib/compliance/compliance-mapper.ts | 30 +++ .../compliance-report-types.test.ts | 2 + ui/lib/compliance/compliance-report-types.ts | 5 +- ui/lib/compliance/csa.tsx | 10 +- ui/lib/compliance/cyber-essentials.tsx | 10 +- ui/lib/compliance/dora.tsx | 10 +- ui/lib/compliance/fedramp-20x.test.ts | 183 ++++++++++++++++++ ui/lib/compliance/fedramp-20x.ts | 110 +++++++++++ ui/lib/compliance/grouped-accordion.tsx | 55 ++++++ ui/lib/compliance/okta-idaas-stig.tsx | 8 +- ui/types/compliance.ts | 16 ++ 18 files changed, 526 insertions(+), 115 deletions(-) create mode 100644 ui/changelog.d/fedramp-20x-cross-provider-breakdown.fixed.md create mode 100644 ui/components/compliance/compliance-custom-details/fedramp-20x-details.tsx rename ui/lib/compliance/{cmmc.tsx => cmmc.ts} (56%) create mode 100644 ui/lib/compliance/fedramp-20x.test.ts create mode 100644 ui/lib/compliance/fedramp-20x.ts create mode 100644 ui/lib/compliance/grouped-accordion.tsx diff --git a/ui/changelog.d/fedramp-20x-cross-provider-breakdown.fixed.md b/ui/changelog.d/fedramp-20x-cross-provider-breakdown.fixed.md new file mode 100644 index 0000000000..dc7c71ce1b --- /dev/null +++ b/ui/changelog.d/fedramp-20x-cross-provider-breakdown.fixed.md @@ -0,0 +1 @@ +Per-provider breakdown and OCSF download for FedRAMP 20x KSI and Class C FRR in the cross-provider compliance view diff --git a/ui/components/compliance/compliance-custom-details/fedramp-20x-details.tsx b/ui/components/compliance/compliance-custom-details/fedramp-20x-details.tsx new file mode 100644 index 0000000000..31f684a33b --- /dev/null +++ b/ui/components/compliance/compliance-custom-details/fedramp-20x-details.tsx @@ -0,0 +1,89 @@ +import { Requirement } from "@/types/compliance"; + +import { + ComplianceBadge, + ComplianceBadgeContainer, + ComplianceDetailContainer, + ComplianceDetailSection, + ComplianceDetailText, +} from "./shared-components"; + +interface FedRAMP20xDetailsProps { + requirement: Requirement; +} + +const DescriptionSection = ({ requirement }: FedRAMP20xDetailsProps) => + requirement.description ? ( + + {requirement.description} + + ) : null; + +export const FedRAMP20xKSICustomDetails = ({ + requirement, +}: FedRAMP20xDetailsProps) => { + return ( + + + + + {requirement.theme && ( + + )} + {requirement.class_applicability && ( + + )} + + + {requirement.nist_controls && ( + + + {requirement.nist_controls as string} + + + )} + + ); +}; + +export const FedRAMP20xFRRCustomDetails = ({ + requirement, +}: FedRAMP20xDetailsProps) => { + return ( + + + + + {requirement.ruleset && ( + + )} + {requirement.subset && ( + + )} + {requirement.force && ( + + )} + + + ); +}; diff --git a/ui/lib/compliance/c5.tsx b/ui/lib/compliance/c5.tsx index 4839df3d66..c39a2dd538 100644 --- a/ui/lib/compliance/c5.tsx +++ b/ui/lib/compliance/c5.tsx @@ -3,13 +3,12 @@ import { ComplianceAccordionRequirementTitle } from "@/components/compliance/com import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; import { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; import { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; -import { +import type { AttributesData, C5AttributesMetadata, Control, Framework, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -20,14 +19,9 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - export const mapComplianceData = ( attributesData: AttributesData, requirementsData: RequirementsData, diff --git a/ui/lib/compliance/cis-controls.tsx b/ui/lib/compliance/cis-controls.tsx index 7a7f283fc6..a1fab412e1 100644 --- a/ui/lib/compliance/cis-controls.tsx +++ b/ui/lib/compliance/cis-controls.tsx @@ -3,12 +3,11 @@ import { ComplianceAccordionRequirementTitle } from "@/components/compliance/com import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; import { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; import { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; -import { +import type { AttributesData, CISControlsAttributesMetadata, Framework, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -19,14 +18,9 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - // Sort the 18 CIS Controls by their leading number ("1. ...", "2. ...", ..., // "18. ...") so the accordion always reads in canonical control order // regardless of how the API returns the sections. diff --git a/ui/lib/compliance/cmmc.tsx b/ui/lib/compliance/cmmc.ts similarity index 56% rename from ui/lib/compliance/cmmc.tsx rename to ui/lib/compliance/cmmc.ts index 557c28b95c..748d0ed39c 100644 --- a/ui/lib/compliance/cmmc.tsx +++ b/ui/lib/compliance/cmmc.ts @@ -1,14 +1,8 @@ -import { ClientAccordionContent } from "@/components/compliance/compliance-accordion/client-accordion-content"; -import { ComplianceAccordionRequirementTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-requeriment-title"; -import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; -import { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; -import { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; -import { +import type { AttributesData, CMMCAttributesMetadata, Framework, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -19,8 +13,11 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; +export { toGroupedAccordionItems as toAccordionItems } from "./grouped-accordion"; + // Canonical NIST SP 800-171 family order for the 14 CMMC domains, so the // accordion always reads in the same order regardless of the API response. export const CMMC_DOMAIN_ORDER: readonly string[] = [ @@ -40,12 +37,6 @@ export const CMMC_DOMAIN_ORDER: readonly string[] = [ "System and Information Integrity", ]; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - export const mapComplianceData = ( attributesData: AttributesData, requirementsData: RequirementsData, @@ -109,56 +100,3 @@ export const mapComplianceData = ( return frameworks; }; - -export const toAccordionItems = ( - data: Framework[], - scanId: string | undefined, -): AccordionItemProps[] => { - const safeId = scanId || ""; - - return data.flatMap((framework) => - framework.categories.map((category) => ({ - key: `${framework.name}-${category.name}`, - title: ( - - ), - content: "", - // Domain → requirements (flat, no intermediate "control" level). - // Keys are derived from the requirement name (which starts with the - // unique CMMC id, e.g. "AC.L1-b.1.i") instead of the array index, so - // expanded state stays attached to the right requirement even if the - // list is reordered or filtered. - items: category.controls.flatMap((control) => - control.requirements.map((requirement) => ({ - key: `${framework.name}-${category.name}-${requirement.name}`, - title: ( - - ), - content: ( - - ), - items: [], - })), - ), - })), - ); -}; diff --git a/ui/lib/compliance/commons.tsx b/ui/lib/compliance/commons.tsx index 24a7b8407c..15b315be4d 100644 --- a/ui/lib/compliance/commons.tsx +++ b/ui/lib/compliance/commons.tsx @@ -7,6 +7,7 @@ import { REQUIREMENT_STATUS, RequirementItemData, RequirementsData, + RequirementsTotals, RequirementStatus, TOP_FAILED_DATA_TYPE, TopFailedDataType, @@ -66,7 +67,7 @@ const incrementFailedCount = ( }; export const updateCounters = ( - target: { pass: number; fail: number; manual: number }, + target: RequirementsTotals, status: RequirementStatus, ) => { if (status === REQUIREMENT_STATUS.MANUAL) { @@ -78,6 +79,14 @@ export const updateCounters = ( } }; +export const getStatusCounters = ( + status: RequirementStatus, +): RequirementsTotals => { + const counters: RequirementsTotals = { pass: 0, fail: 0, manual: 0 }; + updateCounters(counters, status); + return counters; +}; + export const getTopFailedSections = ( mappedData: Framework[], ): TopFailedResult => { diff --git a/ui/lib/compliance/compliance-mapper.test.ts b/ui/lib/compliance/compliance-mapper.test.ts index c7ce69040e..be7ba8074c 100644 --- a/ui/lib/compliance/compliance-mapper.test.ts +++ b/ui/lib/compliance/compliance-mapper.test.ts @@ -54,6 +54,13 @@ vi.mock( "@/components/compliance/compliance-custom-details/ens-details", () => ({ ENSCustomDetails: stubFactory("ENSStub") }), ); +vi.mock( + "@/components/compliance/compliance-custom-details/fedramp-20x-details", + () => ({ + FedRAMP20xFRRCustomDetails: stubFactory("FedRAMP20xFRRStub"), + FedRAMP20xKSICustomDetails: stubFactory("FedRAMP20xKSIStub"), + }), +); vi.mock( "@/components/compliance/compliance-custom-details/generic-details", () => ({ GenericCustomDetails: stubFactory("GenericStub") }), @@ -159,6 +166,8 @@ describe("getComplianceMapper", () => { { framework: "CMMC", expected: "CMMCStub" }, { framework: "Okta-IDaaS-STIG", expected: "OktaIDaaSStigStub" }, { framework: "Cyber-Essentials", expected: "CyberEssentialsStub" }, + { framework: "FedRAMP-20x-KSI", expected: "FedRAMP20xKSIStub" }, + { framework: "FedRAMP-20x-FRR-Class-C", expected: "FedRAMP20xFRRStub" }, ]; for (const { framework, expected } of wiring) { @@ -206,6 +215,8 @@ describe("getComplianceMapper", () => { "CMMC", "Okta-IDaaS-STIG", "Cyber-Essentials", + "FedRAMP-20x-KSI", + "FedRAMP-20x-FRR-Class-C", ]) { const mapper = getComplianceMapper(framework); expect(Object.keys(mapper).sort(), framework).toEqual(expectedKeys); diff --git a/ui/lib/compliance/compliance-mapper.ts b/ui/lib/compliance/compliance-mapper.ts index 80b3558aeb..d80a980485 100644 --- a/ui/lib/compliance/compliance-mapper.ts +++ b/ui/lib/compliance/compliance-mapper.ts @@ -11,6 +11,10 @@ import { CSACustomDetails } from "@/components/compliance/compliance-custom-deta import { CyberEssentialsCustomDetails } from "@/components/compliance/compliance-custom-details/cyber-essentials-details"; import { DORACustomDetails } from "@/components/compliance/compliance-custom-details/dora-details"; import { ENSCustomDetails } from "@/components/compliance/compliance-custom-details/ens-details"; +import { + FedRAMP20xFRRCustomDetails, + FedRAMP20xKSICustomDetails, +} from "@/components/compliance/compliance-custom-details/fedramp-20x-details"; import { GenericCustomDetails } from "@/components/compliance/compliance-custom-details/generic-details"; import { ISOCustomDetails } from "@/components/compliance/compliance-custom-details/iso-details"; import { KISACustomDetails } from "@/components/compliance/compliance-custom-details/kisa-details"; @@ -72,6 +76,11 @@ import { mapComplianceData as mapENSComplianceData, toAccordionItems as toENSAccordionItems, } from "./ens"; +import { + mapFRRComplianceData as mapFedRAMP20xFRRComplianceData, + mapKSIComplianceData as mapFedRAMP20xKSIComplianceData, + toAccordionItems as toFedRAMP20xAccordionItems, +} from "./fedramp-20x"; import { mapComplianceData as mapGenericComplianceData, toAccordionItems as toGenericAccordionItems, @@ -296,6 +305,27 @@ const getComplianceMappers = (): Record => ({ getDetailsComponent: (requirement: Requirement) => createElement(CMMCCustomDetails, { requirement }), }, + // Universal frameworks must compose requirement names as `${id} - ${name}` + // (see `composeRequirementName`); the generic mapper does not, so they need + // a dedicated entry for the cross-provider breakdown to render. + "FedRAMP-20x-KSI": { + mapComplianceData: mapFedRAMP20xKSIComplianceData, + toAccordionItems: toFedRAMP20xAccordionItems, + getTopFailedSections, + calculateCategoryHeatmapData: (data: Framework[]) => + calculateCategoryHeatmapData(data), + getDetailsComponent: (requirement: Requirement) => + createElement(FedRAMP20xKSICustomDetails, { requirement }), + }, + "FedRAMP-20x-FRR-Class-C": { + mapComplianceData: mapFedRAMP20xFRRComplianceData, + toAccordionItems: toFedRAMP20xAccordionItems, + getTopFailedSections, + calculateCategoryHeatmapData: (data: Framework[]) => + calculateCategoryHeatmapData(data), + getDetailsComponent: (requirement: Requirement) => + createElement(FedRAMP20xFRRCustomDetails, { requirement }), + }, }); /** diff --git a/ui/lib/compliance/compliance-report-types.test.ts b/ui/lib/compliance/compliance-report-types.test.ts index 8a431d9748..59b26beed3 100644 --- a/ui/lib/compliance/compliance-report-types.test.ts +++ b/ui/lib/compliance/compliance-report-types.test.ts @@ -41,6 +41,8 @@ describe("isOcsfSupported", () => { expect(isOcsfSupported("csa_ccm_4.0")).toBe(true); expect(isOcsfSupported("cis_controls_8.1")).toBe(true); expect(isOcsfSupported("cmmc_2.0")).toBe(true); + expect(isOcsfSupported("fedramp_20x_ksi_2026")).toBe(true); + expect(isOcsfSupported("fedramp_20x_frr_class_c_2026")).toBe(true); }); it("returns false for legacy/per-provider frameworks without OCSF output", () => { diff --git a/ui/lib/compliance/compliance-report-types.ts b/ui/lib/compliance/compliance-report-types.ts index 68ef3072de..2553df013d 100644 --- a/ui/lib/compliance/compliance-report-types.ts +++ b/ui/lib/compliance/compliance-report-types.ts @@ -167,7 +167,8 @@ export const pickLatestCisPerProvider = ( * Only universal compliance frameworks that declare an ``outputs`` block in * their schema (see ``prowler/compliance/.json``) produce a dedicated * OCSF artifact during scan output generation. Today that is DORA, - * CSA CCM 4.0, CIS Controls 8.1 and CMMC 2.0. Any other framework only + * CSA CCM 4.0, CIS Controls 8.1, CMMC 2.0 and FedRAMP 20x (KSI and Class C + * FRR). Any other framework only * offers CSV (and, for the curated list above, PDF). * * Keep this Set in lock-step with the backend: ``get_prowler_provider_compliance`` @@ -182,6 +183,8 @@ const OCSF_SUPPORTED_COMPLIANCE_IDS: ReadonlySet = new Set([ "csa_ccm_4.0", "cis_controls_8.1", "cmmc_2.0", + "fedramp_20x_ksi_2026", + "fedramp_20x_frr_class_c_2026", ]); export const isOcsfSupported = (complianceId: string | undefined): boolean => diff --git a/ui/lib/compliance/csa.tsx b/ui/lib/compliance/csa.tsx index 3bb601de0c..c38136b19f 100644 --- a/ui/lib/compliance/csa.tsx +++ b/ui/lib/compliance/csa.tsx @@ -4,12 +4,11 @@ import { ComplianceAccordionTitle } from "@/components/compliance/compliance-acc import { ComplianceBadgeVariant } from "@/components/compliance/compliance-custom-details/shared-components"; import { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; import { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; -import { +import type { AttributesData, CSAAttributesMetadata, Framework, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -20,6 +19,7 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; export interface CSAMappingSection { @@ -36,12 +36,6 @@ export const CSA_MAPPING_SECTIONS: CSAMappingSection[] = [ }, ]; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - export const mapComplianceData = ( attributesData: AttributesData, requirementsData: RequirementsData, diff --git a/ui/lib/compliance/cyber-essentials.tsx b/ui/lib/compliance/cyber-essentials.tsx index aee4d8c5db..ebdd73209d 100644 --- a/ui/lib/compliance/cyber-essentials.tsx +++ b/ui/lib/compliance/cyber-essentials.tsx @@ -3,12 +3,11 @@ import { ComplianceAccordionRequirementTitle } from "@/components/compliance/com import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; import { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; import { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; -import { +import type { AttributesData, CyberEssentialsAttributesMetadata, Framework, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -19,6 +18,7 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; // Display order for the five Cyber Essentials control themes in the accordion @@ -33,12 +33,6 @@ export const CYBER_ESSENTIALS_THEME_ORDER: readonly string[] = [ "Malware Protection", ]; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - export const mapComplianceData = ( attributesData: AttributesData, requirementsData: RequirementsData, diff --git a/ui/lib/compliance/dora.tsx b/ui/lib/compliance/dora.tsx index 8ac364f29f..7fc6bba26c 100644 --- a/ui/lib/compliance/dora.tsx +++ b/ui/lib/compliance/dora.tsx @@ -3,12 +3,11 @@ import { ComplianceAccordionRequirementTitle } from "@/components/compliance/com import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; import { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; import { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; -import { +import type { AttributesData, DORAAttributesMetadata, Framework, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -19,6 +18,7 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; // Display order for DORA pillars in the accordion and any grouped chart. The @@ -33,12 +33,6 @@ export const DORA_PILLAR_ORDER: readonly string[] = [ "Information Sharing", ]; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - export const mapComplianceData = ( attributesData: AttributesData, requirementsData: RequirementsData, diff --git a/ui/lib/compliance/fedramp-20x.test.ts b/ui/lib/compliance/fedramp-20x.test.ts new file mode 100644 index 0000000000..21d40c69bc --- /dev/null +++ b/ui/lib/compliance/fedramp-20x.test.ts @@ -0,0 +1,183 @@ +import { describe, expect, it, vi } from "vitest"; + +vi.mock( + "@/components/compliance/compliance-accordion/client-accordion-content", + () => ({ ClientAccordionContent: () => null }), +); +vi.mock( + "@/components/compliance/compliance-accordion/compliance-accordion-requeriment-title", + () => ({ ComplianceAccordionRequirementTitle: () => null }), +); +vi.mock( + "@/components/compliance/compliance-accordion/compliance-accordion-title", + () => ({ ComplianceAccordionTitle: () => null }), +); + +import { + buildRequirementExtrasMap, + crossProviderToMapperInput, +} from "@/app/(prowler)/compliance/_lib/cross-provider-adapter"; +import type { CrossProviderOverviewAttributes } from "@/app/(prowler)/compliance/_types"; +import { Framework, Requirement } from "@/types/compliance"; + +import { + mapFRRComplianceData, + mapKSIComplianceData, + toAccordionItems, +} from "./fedramp-20x"; + +type OverviewRequirement = + CrossProviderOverviewAttributes["requirements"][number]; + +const buildOverview = ( + framework: string, + requirements: Array>, +): CrossProviderOverviewAttributes => + ({ + framework, + version: "2026", + description: "", + providers: ["aws"], + compatible_providers: ["aws"], + scan_ids_by_provider: {}, + requirements: requirements.map((requirement) => ({ + ...requirement, + description: "Requirement text.", + status: "PASS", + providers: { aws: "PASS" }, + check_ids_by_provider: { aws: ["check_one"] }, + })), + }) as unknown as CrossProviderOverviewAttributes; + +const mapOverview = ( + overview: CrossProviderOverviewAttributes, + mapper: typeof mapKSIComplianceData, +): Framework[] => { + const { attributesData, requirementsData } = + crossProviderToMapperInput(overview); + return mapper(attributesData, requirementsData); +}; + +const allRequirements = (frameworks: Framework[]): Requirement[] => + frameworks.flatMap((framework) => + framework.categories.flatMap((category) => + category.controls.flatMap((control) => control.requirements), + ), + ); + +const KSI_OVERVIEW = buildOverview("FedRAMP-20x-KSI", [ + { + id: "KSI-SVC-VRI", + name: "Validating Resource Integrity", + attributes: { + Theme: "KSI-SVC: Service Configuration", + NISTControls: "SC-13", + ClassApplicability: "Required for Classes B and C", + }, + }, + { + id: "KSI-CED-RAT", + name: "Reviewing All Training", + attributes: { + Theme: "KSI-CED: Cybersecurity Education", + NISTControls: null, + ClassApplicability: "Required for Classes B and C", + }, + }, +]); + +const FRR_OVERVIEW = buildOverview("FedRAMP-20x-FRR-Class-C", [ + { + id: "CMU-CSO-UVM", + name: "Using Validated Cryptographic Modules", + attributes: { + Ruleset: "CMU: Cryptographic Module Use", + Subset: "CSO: Cloud Service Provider Responsibilities", + Force: "MUST", + }, + }, + { + id: "AFC-CSO-INB", + name: "Maintain a FedRAMP Security Inbox", + attributes: { + Ruleset: "AFC: Addressing FedRAMP Communication", + Subset: "CSO: General Provider Responsibilities", + Force: "MUST", + }, + }, +]); + +describe.each([ + { label: "KSI", overview: KSI_OVERVIEW, mapper: mapKSIComplianceData }, + { + label: "FRR Class C", + overview: FRR_OVERVIEW, + mapper: mapFRRComplianceData, + }, +])("FedRAMP 20x $label cross-provider join", ({ overview, mapper }) => { + it("names every requirement with a key of the per-provider breakdown", () => { + const extras = buildRequirementExtrasMap(overview); + const names = allRequirements(mapOverview(overview, mapper)).map( + (requirement) => requirement.name, + ); + + expect(names).toHaveLength(overview.requirements.length); + for (const name of names) { + expect(extras.has(name), name).toBe(true); + } + }); +}); + +describe("mapKSIComplianceData", () => { + it("groups by Theme in catalog order and exposes KSI attributes", () => { + const [framework] = mapOverview(KSI_OVERVIEW, mapKSIComplianceData); + + expect(framework.categories.map((category) => category.name)).toEqual([ + "KSI-CED: Cybersecurity Education", + "KSI-SVC: Service Configuration", + ]); + + const [svc] = framework.categories[1].controls[0].requirements; + expect(svc.name).toBe("KSI-SVC-VRI - Validating Resource Integrity"); + expect(svc.theme).toBe("KSI-SVC: Service Configuration"); + expect(svc.nist_controls).toBe("SC-13"); + expect(svc.class_applicability).toBe("Required for Classes B and C"); + + const [ced] = framework.categories[0].controls[0].requirements; + expect(ced.nist_controls).toBeUndefined(); + }); +}); + +describe("mapFRRComplianceData", () => { + it("groups by Ruleset in catalog order and exposes FRR attributes", () => { + const [framework] = mapOverview(FRR_OVERVIEW, mapFRRComplianceData); + + expect(framework.categories.map((category) => category.name)).toEqual([ + "AFC: Addressing FedRAMP Communication", + "CMU: Cryptographic Module Use", + ]); + + const [cmu] = framework.categories[1].controls[0].requirements; + expect(cmu.ruleset).toBe("CMU: Cryptographic Module Use"); + expect(cmu.subset).toBe("CSO: Cloud Service Provider Responsibilities"); + expect(cmu.force).toBe("MUST"); + expect(framework.pass).toBe(2); + }); +}); + +describe("toAccordionItems (FedRAMP 20x)", () => { + it("keys requirement leaves by name instead of position", () => { + const items = toAccordionItems( + mapOverview(FRR_OVERVIEW, mapFRRComplianceData), + "scan-1", + ); + + expect(items.map((item) => item.key)).toEqual([ + "FedRAMP-20x-FRR-Class-C-AFC: Addressing FedRAMP Communication", + "FedRAMP-20x-FRR-Class-C-CMU: Cryptographic Module Use", + ]); + expect(items[1].items?.[0]?.key).toBe( + "FedRAMP-20x-FRR-Class-C-CMU: Cryptographic Module Use-CMU-CSO-UVM - Using Validated Cryptographic Modules", + ); + }); +}); diff --git a/ui/lib/compliance/fedramp-20x.ts b/ui/lib/compliance/fedramp-20x.ts new file mode 100644 index 0000000000..fd7d9fb1a3 --- /dev/null +++ b/ui/lib/compliance/fedramp-20x.ts @@ -0,0 +1,110 @@ +import type { + AttributesData, + FedRAMP20xFRRAttributesMetadata, + FedRAMP20xKSIAttributesMetadata, + Framework, + Requirement, + RequirementsData, + RequirementStatus, +} from "@/types/compliance"; + +import { + calculateFrameworkCounters, + createRequirementsMap, + findOrCreateCategory, + findOrCreateControl, + findOrCreateFramework, + getStatusCounters, +} from "./commons"; + +export { toGroupedAccordionItems as toAccordionItems } from "./grouped-accordion"; + +type RequirementFields = Record; + +const mapByGroup = ( + attributesData: AttributesData, + requirementsData: RequirementsData, + getGroup: (attrs: TMetadata) => string, + getFields: (attrs: TMetadata) => RequirementFields, +): Framework[] => { + const attributes = attributesData?.data || []; + const requirementsMap = createRequirementsMap(requirementsData); + const frameworks: Framework[] = []; + + for (const attributeItem of attributes) { + const id = attributeItem.id; + const metadataArray = attributeItem.attributes?.attributes + ?.metadata as unknown as TMetadata[]; + const attrs = metadataArray?.[0]; + if (!attrs) continue; + + const requirementData = requirementsMap.get(id); + if (!requirementData) continue; + + const categoryName = getGroup(attrs); + const requirementName = attributeItem.attributes.name || ""; + const status = (requirementData.attributes.status || + "") as RequirementStatus; + + const framework = findOrCreateFramework( + frameworks, + attributeItem.attributes.framework, + ); + const category = findOrCreateCategory(framework.categories, categoryName); + const control = findOrCreateControl(category.controls, categoryName); + + // The name must match `composeRequirementName` in the cross-provider + // adapter, or the per-provider breakdown cannot be joined. + const requirement: Requirement = { + ...getFields(attrs), + name: requirementName ? `${id} - ${requirementName}` : id, + description: attributeItem.attributes.description, + status, + check_ids: attributeItem.attributes.attributes.check_ids || [], + invalid_config: requirementData.attributes.invalid_config || false, + ...getStatusCounters(status), + }; + + control.requirements.push(requirement); + } + + // Theme and Ruleset names start with their catalog code, so alphabetical + // order is the catalog order. + for (const framework of frameworks) { + framework.categories.sort((a, b) => a.name.localeCompare(b.name)); + } + + calculateFrameworkCounters(frameworks); + + return frameworks; +}; + +export const mapKSIComplianceData = ( + attributesData: AttributesData, + requirementsData: RequirementsData, +): Framework[] => + mapByGroup( + attributesData, + requirementsData, + (attrs) => attrs.Theme, + (attrs) => ({ + theme: attrs.Theme, + nist_controls: attrs.NISTControls || undefined, + class_applicability: attrs.ClassApplicability, + }), + ); + +export const mapFRRComplianceData = ( + attributesData: AttributesData, + requirementsData: RequirementsData, +): Framework[] => + mapByGroup( + attributesData, + requirementsData, + (attrs) => attrs.Ruleset, + (attrs) => ({ + ruleset: attrs.Ruleset, + subset: attrs.Subset, + force: attrs.Force, + }), + ); diff --git a/ui/lib/compliance/grouped-accordion.tsx b/ui/lib/compliance/grouped-accordion.tsx new file mode 100644 index 0000000000..cea6651079 --- /dev/null +++ b/ui/lib/compliance/grouped-accordion.tsx @@ -0,0 +1,55 @@ +import { ClientAccordionContent } from "@/components/compliance/compliance-accordion/client-accordion-content"; +import { ComplianceAccordionRequirementTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-requeriment-title"; +import { ComplianceAccordionTitle } from "@/components/compliance/compliance-accordion/compliance-accordion-title"; +import type { AccordionItemProps } from "@/components/shadcn/accordion/Accordion"; +import type { FindingStatus } from "@/components/shadcn/table/status-finding-badge"; +import type { Framework } from "@/types/compliance"; + +/** Category → requirement accordion, with stable keys across reordering. */ +export const toGroupedAccordionItems = ( + data: Framework[], + scanId: string | undefined, +): AccordionItemProps[] => { + const safeId = scanId || ""; + + return data.flatMap((framework) => + framework.categories.map((category) => ({ + key: `${framework.name}-${category.name}`, + title: ( + + ), + content: "", + items: category.controls.flatMap((control) => + control.requirements.map((requirement) => ({ + key: `${framework.name}-${category.name}-${requirement.name}`, + title: ( + + ), + content: ( + + ), + items: [], + })), + ), + })), + ); +}; diff --git a/ui/lib/compliance/okta-idaas-stig.tsx b/ui/lib/compliance/okta-idaas-stig.tsx index 8603c33711..3d8b797b8a 100644 --- a/ui/lib/compliance/okta-idaas-stig.tsx +++ b/ui/lib/compliance/okta-idaas-stig.tsx @@ -10,7 +10,6 @@ import { isOktaIDaaSStigAttributesMetadata, OktaIDaaSStigRequirement, Requirement, - REQUIREMENT_STATUS, RequirementsData, RequirementStatus, } from "@/types/compliance"; @@ -21,14 +20,9 @@ import { findOrCreateCategory, findOrCreateControl, findOrCreateFramework, + getStatusCounters, } from "./commons"; -const getStatusCounters = (status: RequirementStatus) => ({ - pass: status === REQUIREMENT_STATUS.PASS ? 1 : 0, - fail: status === REQUIREMENT_STATUS.FAIL ? 1 : 0, - manual: status === REQUIREMENT_STATUS.MANUAL ? 1 : 0, -}); - export const mapComplianceData = ( attributesData: AttributesData, requirementsData: RequirementsData, diff --git a/ui/types/compliance.ts b/ui/types/compliance.ts index be7462f549..e7f27a8e09 100644 --- a/ui/types/compliance.ts +++ b/ui/types/compliance.ts @@ -474,6 +474,20 @@ export interface CMMCAttributesMetadata { SourceRequirement: string; } +// FedRAMP 20x KSI (`prowler/compliance/fedramp_20x_ksi_2026.json`), grouped by Theme. +export interface FedRAMP20xKSIAttributesMetadata { + Theme: string; + NISTControls?: string | null; + ClassApplicability: string; +} + +// FedRAMP 20x Class C FRR (`prowler/compliance/fedramp_20x_frr_class_c_2026.json`), grouped by Ruleset. +export interface FedRAMP20xFRRAttributesMetadata { + Ruleset: string; + Subset: string; + Force: string; +} + export interface AttributesItemData { type: "compliance-requirements-attributes"; id: string; @@ -501,6 +515,8 @@ export interface AttributesItemData { | CISControlsAttributesMetadata[] | CyberEssentialsAttributesMetadata[] | CMMCAttributesMetadata[] + | FedRAMP20xKSIAttributesMetadata[] + | FedRAMP20xFRRAttributesMetadata[] | GenericAttributesMetadata[]; check_ids: string[]; // MITRE structure From 757cd44ecbc306137723163881e9b3703ac9dbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 16 Sep 2026 09:24:41 +0200 Subject: [PATCH 62/77] fix(aws): try the rest of the partition when the bootstrap region is unreachable (#12799) Co-authored-by: pedrooot --- .../providers/aws/regions-and-partitions.mdx | 2 + ...rap-falls-back-to-the-next-region.fixed.md | 1 + prowler/providers/aws/aws_provider.py | 150 ++++++- tests/providers/aws/aws_provider_test.py | 408 ++++++++++++++++++ 4 files changed, 548 insertions(+), 13 deletions(-) create mode 100644 prowler/changelog.d/aws-partition-bootstrap-falls-back-to-the-next-region.fixed.md diff --git a/docs/user-guide/providers/aws/regions-and-partitions.mdx b/docs/user-guide/providers/aws/regions-and-partitions.mdx index bf88aafc2f..369f581826 100644 --- a/docs/user-guide/providers/aws/regions-and-partitions.mdx +++ b/docs/user-guide/providers/aws/regions-and-partitions.mdx @@ -39,6 +39,8 @@ It matters most where nothing else says. Resolving an identity means calling STS A region configured for the session still wins when it belongs to the declared partition, so a deployment in `us-gov-west-1` is not sent to `us-gov-east-1`. A region belonging to a different partition is ignored, since a partition that has been declared explicitly is the more deliberate statement of the two. +When no configured region says which one to prefer, the first region of the partition is tried, and up to two more follow if it cannot be reached. A network that routes to only one region of its partition therefore works without having to declare which one that is. Only a connection failure moves on to the next region: a credential error is reported from the first, since it would be the same everywhere. A region excluded from the scan is tried last, so it is avoided whenever another region of the partition answers. + Set it wherever the scan runs. For deployments that scan from containers, that means the environment of the containers doing the scanning, not only the one accepting the request. diff --git a/prowler/changelog.d/aws-partition-bootstrap-falls-back-to-the-next-region.fixed.md b/prowler/changelog.d/aws-partition-bootstrap-falls-back-to-the-next-region.fixed.md new file mode 100644 index 0000000000..4bd9c855d1 --- /dev/null +++ b/prowler/changelog.d/aws-partition-bootstrap-falls-back-to-the-next-region.fixed.md @@ -0,0 +1 @@ +Bootstrap STS calls now try up to two more regions of the partition declared in `PROWLER_AWS_PARTITION` when the first one cannot be reached, so a deployment that routes to only one region of its partition no longer fails on an endpoint it has no path to. This covers validating credentials, assuming a role and getting an MFA session token diff --git a/prowler/providers/aws/aws_provider.py b/prowler/providers/aws/aws_provider.py index e204318593..784daf0caa 100644 --- a/prowler/providers/aws/aws_provider.py +++ b/prowler/providers/aws/aws_provider.py @@ -3,12 +3,19 @@ import pathlib from datetime import datetime from functools import lru_cache from re import fullmatch -from typing import Optional +from typing import Any, Callable, Optional from boto3.session import Session from botocore.config import Config from botocore.credentials import RefreshableCredentials -from botocore.exceptions import ClientError, NoCredentialsError, ProfileNotFound +from botocore.exceptions import ( + ClientError, + ConnectTimeoutError, + EndpointConnectionError, + NoCredentialsError, + ProfileNotFound, + ReadTimeoutError, +) from botocore.session import Session as BotocoreSession from colorama import Fore, Style from pytz import utc @@ -263,7 +270,10 @@ class AwsProvider(Provider): caller_identity = self.validate_credentials( session=self.session.current_session, aws_region=sts_region, + excluded_regions=excluded_regions, ) + # Later STS calls go where validation got an answer, not where it timed out + sts_region = caller_identity.region logger.info("Credentials validated") ######## @@ -690,8 +700,6 @@ class AwsProvider(Provider): or session.region_name or AWS_STS_GLOBAL_ENDPOINT_REGION ) - sts_client = AwsProvider.create_sts_session(session, sts_region) - # TODO: pass values from the input mfa_info = AwsProvider.input_role_mfa_token_and_code() # TODO: validate MFA ARN here @@ -699,8 +707,12 @@ class AwsProvider(Provider): "SerialNumber": mfa_info.arn, "TokenCode": mfa_info.totp, } - session_credentials = sts_client.get_session_token( - **get_session_token_arguments + _, session_credentials = AwsProvider.sts_call_with_partition_failover( + session, + sts_region, + lambda sts_client: sts_client.get_session_token( + **get_session_token_arguments + ), ) mfa_session = Session( aws_access_key_id=session_credentials["Credentials"]["AccessKeyId"], @@ -1244,10 +1256,11 @@ class AwsProvider(Provider): mfa_info = AwsProvider.input_role_mfa_token_and_code() assume_role_arguments["SerialNumber"] = mfa_info.arn assume_role_arguments["TokenCode"] = mfa_info.totp - sts_client = AwsProvider.create_sts_session( - session, assumed_role_info.sts_region + _, assumed_credentials = AwsProvider.sts_call_with_partition_failover( + session, + assumed_role_info.sts_region, + lambda sts_client: sts_client.assume_role(**assume_role_arguments), ) - assumed_credentials = sts_client.assume_role(**assume_role_arguments) # Convert the UTC datetime object to your local timezone credentials_expiration_local_time = ( assumed_credentials["Credentials"]["Expiration"] @@ -1326,30 +1339,98 @@ class AwsProvider(Provider): ) raise error + @staticmethod + def sts_call_with_partition_failover( + session: Session, + aws_region: str, + operation: Callable[[Any], Any], + excluded_regions: set[str] | None = None, + ) -> tuple[str, Any]: + """ + Run a bootstrap STS call, moving on when a region cannot be reached. + + Bootstrap calls happen before anything is known about the credentials, so + the region they go to is a guess whenever none was configured. On a network + that routes to only one region of its partition that guess is fatal, and the + remaining regions of the partition declared in PROWLER_AWS_PARTITION are the + ones worth trying. + + Args: + session (Session): The AWS session object. + aws_region (str): The region to try first. + operation (Callable[[Any], Any]): Receives an STS client and performs + the call. + excluded_regions (set[str] | None): Regions excluded from the scan, + tried after the rest of the partition. + + Returns: + tuple[str, Any]: The region that answered and whatever the operation + returned. + + Raises: + Exception: Whatever the operation raises, or the last connection error + when no region could be reached. + """ + *fallback_regions, last_region = get_partition_bootstrap_candidates( + aws_region, session.region_name, excluded_regions + ) + + for candidate_region in fallback_regions: + try: + sts_client = AwsProvider.create_sts_session(session, candidate_region) + return candidate_region, operation(sts_client) + # The credentials are not at fault, so the next region is worth trying + except ( + EndpointConnectionError, + ConnectTimeoutError, + ReadTimeoutError, + ) as unreachable: + logger.warning( + f"{unreachable.__class__.__name__}[{unreachable.__traceback__.tb_lineno}]: {unreachable}" + ) + + # Nothing is left to try after the last region, so its error is the answer + sts_client = AwsProvider.create_sts_session(session, last_region) + return last_region, operation(sts_client) + @staticmethod def validate_credentials( session: Session, aws_region: str, + excluded_regions: set[str] | None = None, ) -> AWSCallerIdentity: """ Validates the AWS credentials using the provided session and AWS region. + + When the region cannot be reached, the remaining regions of the partition + declared in PROWLER_AWS_PARTITION are tried before giving up. A credential + error is returned from the first region instead, since it would be the same + everywhere. + Args: session (Session): The AWS session object. aws_region (str): The AWS region to validate the credentials. + excluded_regions (set[str] | None): Regions excluded from the scan, + tried after the rest of the partition. Returns: - AWSCallerIdentity: An object containing the caller identity information. + AWSCallerIdentity: An object containing the caller identity information, + including the region that answered. Raises: Exception: If an error occurs during the validation process. """ try: - sts_client = AwsProvider.create_sts_session(session, aws_region) - caller_identity = sts_client.get_caller_identity() + sts_region, caller_identity = AwsProvider.sts_call_with_partition_failover( + session, + aws_region, + lambda sts_client: sts_client.get_caller_identity(), + excluded_regions, + ) # Include the region where the caller_identity has validated the credentials return AWSCallerIdentity( user_id=caller_identity.get("UserId"), account=caller_identity.get("Account"), arn=ARN(caller_identity.get("Arn")), - region=aws_region, + region=sts_region, ) except ClientError as client_error: logger.error( @@ -1846,6 +1927,49 @@ def get_env_partition_bootstrap_region( return regions[0] if regions else None +# An unreachable endpoint costs a connection timeout, so a partition with many +# regions is not walked in full +MAX_STS_BOOTSTRAP_ATTEMPTS = 3 + + +def get_partition_bootstrap_candidates( + aws_region: str, + session_region: Optional[str] = None, + excluded_regions: set[str] | None = None, +) -> list: + """ + Get the STS bootstrap regions to try, in order, starting with the chosen one. + + A deployment reached only through its own region's endpoints has no route to + the rest of its partition, and which region that is cannot be known from the + environment alone: a container may carry a region belonging to no partition + it scans. Offering the remaining regions of the declared partition lets the + bootstrap succeed without anything having to declare the right one. + + Args: + aws_region (str): The region already chosen for the bootstrap call. + session_region (Optional[str]): The region of the AWS session. + excluded_regions (set[str] | None): Regions excluded from the scan. They + go after the rest of the partition, so the bootstrap avoids them + whenever another region answers and still has them as a last resort. + + Returns: + list: The regions to try, preferred first, capped at + MAX_STS_BOOTSTRAP_ATTEMPTS. + """ + excluded_regions = set(excluded_regions or ()) + partition_regions = get_env_partition_regions(session_region) or [] + # sorted() is stable, so the partition order survives on each side of the split + ordered_regions = sorted( + partition_regions, key=lambda region: region in excluded_regions + ) + candidates = [aws_region] + for region in ordered_regions: + if region not in candidates: + candidates.append(region) + return candidates[:MAX_STS_BOOTSTRAP_ATTEMPTS] + + # TODO: This can be moved to another class since it doesn't need self def get_aws_region_for_sts( session_region: str, diff --git a/tests/providers/aws/aws_provider_test.py b/tests/providers/aws/aws_provider_test.py index f899706453..2d759f362a 100644 --- a/tests/providers/aws/aws_provider_test.py +++ b/tests/providers/aws/aws_provider_test.py @@ -17,10 +17,12 @@ from pytest import raises from tzlocal import get_localzone from prowler.providers.aws.aws_provider import ( + MAX_STS_BOOTSTRAP_ATTEMPTS, AwsProvider, get_aws_region_for_sts, get_env_partition_bootstrap_region, get_env_partition_regions, + get_partition_bootstrap_candidates, ) from prowler.providers.aws.config import ( AWS_STS_GLOBAL_ENDPOINT_REGION, @@ -32,6 +34,7 @@ from prowler.providers.aws.config import ( get_default_session_config, ) from prowler.providers.aws.exceptions.exceptions import ( + AWSAccessKeyIDInvalidError, AWSArgumentTypeValidationError, AWSIAMRoleARNInvalidResourceTypeError, AWSInvalidBoto3TimeoutError, @@ -1583,6 +1586,411 @@ aws: assert get_caller_identity.arn.resource == "test-user" assert get_caller_identity.arn.resource_type == "user" + def test_get_partition_bootstrap_candidates_adds_the_rest_of_the_partition( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + + assert get_partition_bootstrap_candidates( + AWS_REGION_GOV_CLOUD_US_EAST_1, AWS_REGION_US_EAST_1 + ) == [AWS_REGION_GOV_CLOUD_US_EAST_1, AWS_REGION_GOV_CLOUD_US_WEST_1] + + def test_get_partition_bootstrap_candidates_without_partition_offers_one_region( + self, monkeypatch + ): + monkeypatch.delenv("PROWLER_AWS_PARTITION", raising=False) + + assert get_partition_bootstrap_candidates(AWS_REGION_EU_WEST_1) == [ + AWS_REGION_EU_WEST_1 + ] + + def test_get_partition_bootstrap_candidates_is_capped(self, monkeypatch): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_COMMERCIAL_PARTITION) + + candidates = get_partition_bootstrap_candidates( + AWS_REGION_EU_WEST_1, AWS_REGION_EU_WEST_1 + ) + + assert len(candidates) == MAX_STS_BOOTSTRAP_ATTEMPTS + assert candidates[0] == AWS_REGION_EU_WEST_1 + + def test_get_partition_bootstrap_candidates_tries_excluded_regions_last( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_COMMERCIAL_PARTITION) + partition_regions = get_env_partition_regions(AWS_REGION_EU_WEST_1) + excluded_regions = set(partition_regions[1:3]) + + candidates = get_partition_bootstrap_candidates( + AWS_REGION_EU_WEST_1, AWS_REGION_EU_WEST_1, excluded_regions + ) + + assert candidates == [AWS_REGION_EU_WEST_1, *partition_regions[3:5]] + + def test_get_partition_bootstrap_candidates_keeps_excluded_regions_as_a_last_resort( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + + assert get_partition_bootstrap_candidates( + AWS_REGION_GOV_CLOUD_US_EAST_1, + AWS_REGION_US_EAST_1, + {AWS_REGION_GOV_CLOUD_US_EAST_1, AWS_REGION_GOV_CLOUD_US_WEST_1}, + ) == [AWS_REGION_GOV_CLOUD_US_EAST_1, AWS_REGION_GOV_CLOUD_US_WEST_1] + + def test_validate_credentials_falls_back_to_the_next_partition_region( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + # A container may carry a region that belongs to no partition it scans + current_session = session.Session(region_name=AWS_REGION_US_EAST_1) + attempted_regions = [] + + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + if aws_region == AWS_REGION_GOV_CLOUD_US_EAST_1: + raise botocore.exceptions.EndpointConnectionError( + endpoint_url=f"https://sts.{aws_region}.amazonaws.com" + ) + sts_client = mock.MagicMock() + sts_client.get_caller_identity.return_value = { + "UserId": "test-user-id", + "Account": AWS_ACCOUNT_NUMBER, + "Arn": AWS_GOV_CLOUD_ACCOUNT_ARN, + } + return sts_client + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ): + caller_identity = AwsProvider.validate_credentials( + session=current_session, aws_region=AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + assert attempted_regions == [ + AWS_REGION_GOV_CLOUD_US_EAST_1, + AWS_REGION_GOV_CLOUD_US_WEST_1, + ] + assert caller_identity.region == AWS_REGION_GOV_CLOUD_US_WEST_1 + + def test_validate_credentials_falls_back_when_a_region_does_not_answer( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + current_session = session.Session(region_name=AWS_REGION_US_EAST_1) + attempted_regions = [] + + # The connection is accepted but nothing comes back before the read timeout + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + if aws_region == AWS_REGION_GOV_CLOUD_US_EAST_1: + raise botocore.exceptions.ReadTimeoutError( + endpoint_url=f"https://sts.{aws_region}.amazonaws.com" + ) + sts_client = mock.MagicMock() + sts_client.get_caller_identity.return_value = { + "UserId": "test-user-id", + "Account": AWS_ACCOUNT_NUMBER, + "Arn": AWS_GOV_CLOUD_ACCOUNT_ARN, + } + return sts_client + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ): + caller_identity = AwsProvider.validate_credentials( + session=current_session, aws_region=AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + assert attempted_regions == [ + AWS_REGION_GOV_CLOUD_US_EAST_1, + AWS_REGION_GOV_CLOUD_US_WEST_1, + ] + assert caller_identity.region == AWS_REGION_GOV_CLOUD_US_WEST_1 + + def test_validate_credentials_raises_when_no_partition_region_answers( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + current_session = session.Session(region_name=AWS_REGION_US_EAST_1) + attempted_regions = [] + + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + raise botocore.exceptions.EndpointConnectionError( + endpoint_url=f"https://sts.{aws_region}.amazonaws.com" + ) + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ): + with raises(botocore.exceptions.EndpointConnectionError): + AwsProvider.validate_credentials( + session=current_session, aws_region=AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + assert attempted_regions == [ + AWS_REGION_GOV_CLOUD_US_EAST_1, + AWS_REGION_GOV_CLOUD_US_WEST_1, + ] + + def test_validate_credentials_avoids_an_excluded_region_when_failing_over( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_COMMERCIAL_PARTITION) + current_session = session.Session(region_name=AWS_REGION_EU_WEST_1) + partition_regions = get_env_partition_regions(AWS_REGION_EU_WEST_1) + excluded_region, answering_region = partition_regions[1:3] + attempted_regions = [] + + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + if aws_region == AWS_REGION_EU_WEST_1: + raise botocore.exceptions.EndpointConnectionError( + endpoint_url=f"https://sts.{aws_region}.amazonaws.com" + ) + sts_client = mock.MagicMock() + sts_client.get_caller_identity.return_value = { + "UserId": "test-user-id", + "Account": AWS_ACCOUNT_NUMBER, + "Arn": AWS_ACCOUNT_ARN, + } + return sts_client + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ): + caller_identity = AwsProvider.validate_credentials( + session=current_session, + aws_region=AWS_REGION_EU_WEST_1, + excluded_regions={excluded_region}, + ) + + assert attempted_regions == [AWS_REGION_EU_WEST_1, answering_region] + assert caller_identity.region == answering_region + + def test_validate_credentials_does_not_retry_a_credential_error(self, monkeypatch): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + current_session = session.Session(region_name=AWS_REGION_US_EAST_1) + attempted_regions = [] + + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + sts_client = mock.MagicMock() + sts_client.get_caller_identity.side_effect = ( + botocore.exceptions.ClientError( + {"Error": {"Code": "InvalidClientTokenId", "Message": "invalid"}}, + "GetCallerIdentity", + ) + ) + return sts_client + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ): + with raises(AWSAccessKeyIDInvalidError): + AwsProvider.validate_credentials( + session=current_session, aws_region=AWS_REGION_GOV_CLOUD_US_EAST_1 + ) + + assert attempted_regions == [AWS_REGION_GOV_CLOUD_US_EAST_1] + + def test_assume_role_falls_back_to_the_next_partition_region(self, monkeypatch): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + current_session = session.Session(region_name=AWS_REGION_US_EAST_1) + attempted_regions = [] + + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + if aws_region == AWS_REGION_GOV_CLOUD_US_EAST_1: + raise botocore.exceptions.EndpointConnectionError( + endpoint_url=f"https://sts.{aws_region}.amazonaws.com" + ) + sts_client = mock.MagicMock() + sts_client.assume_role.return_value = { + "Credentials": { + "AccessKeyId": "AKIAIOSFODNN7EXAMPLE", + "SecretAccessKey": "secret", + "SessionToken": "token", + "Expiration": datetime.now() + timedelta(seconds=3600), + } + } + return sts_client + + assumed_role_info = AWSAssumeRoleInfo( + role_arn=ARN( + arn=f"arn:{AWS_GOV_CLOUD_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:role/test-role" + ), + session_duration=3600, + external_id=None, + mfa_enabled=False, + role_session_name=ROLE_SESSION_NAME, + sts_region=AWS_REGION_GOV_CLOUD_US_EAST_1, + ) + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ): + credentials = AwsProvider.assume_role(current_session, assumed_role_info) + + assert attempted_regions == [ + AWS_REGION_GOV_CLOUD_US_EAST_1, + AWS_REGION_GOV_CLOUD_US_WEST_1, + ] + assert isinstance(credentials, AWSCredentials) + assert credentials.aws_access_key_id == "AKIAIOSFODNN7EXAMPLE" + + def test_setup_session_mfa_falls_back_to_the_next_partition_region( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + monkeypatch.setenv("AWS_DEFAULT_REGION", AWS_REGION_US_EAST_1) + attempted_regions = [] + + def create_sts_session(session, aws_region): + attempted_regions.append(aws_region) + if aws_region == AWS_REGION_GOV_CLOUD_US_EAST_1: + raise botocore.exceptions.EndpointConnectionError( + endpoint_url=f"https://sts.{aws_region}.amazonaws.com" + ) + sts_client = mock.MagicMock() + sts_client.get_session_token.return_value = { + "Credentials": { + "AccessKeyId": "AKIAIOSFODNN7EXAMPLE", + "SecretAccessKey": "secret", + "SessionToken": "token", + } + } + return sts_client + + with ( + patch( + "prowler.providers.aws.aws_provider.AwsProvider.input_role_mfa_token_and_code", + return_value=AWSMFAInfo( + arn=f"arn:{AWS_GOV_CLOUD_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:mfa/test", + totp="123456", + ), + ), + patch( + "prowler.providers.aws.aws_provider.AwsProvider.create_sts_session", + new=create_sts_session, + ), + ): + mfa_session = AwsProvider.setup_session( + mfa=True, + aws_access_key_id="test-access-key", + aws_secret_access_key="test-secret-key", + ) + + assert attempted_regions == [ + AWS_REGION_GOV_CLOUD_US_EAST_1, + AWS_REGION_GOV_CLOUD_US_WEST_1, + ] + assert mfa_session.get_credentials().access_key == "AKIAIOSFODNN7EXAMPLE" + assert mfa_session.get_credentials().token == "token" + + @mock_aws + def test_aws_provider_hands_excluded_regions_to_credential_validation( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + monkeypatch.setenv("AWS_DEFAULT_REGION", AWS_REGION_US_EAST_1) + handed = [] + + class Validated(Exception): + pass + + # Stops at the validation: what it was handed is all this checks + def validate_credentials(session, aws_region, excluded_regions=None): + handed.append((aws_region, set(excluded_regions or ()))) + raise Validated + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.validate_credentials", + side_effect=validate_credentials, + ): + with raises(Validated): + AwsProvider(excluded_regions={AWS_REGION_GOV_CLOUD_US_EAST_1}) + + assert handed == [ + (AWS_REGION_GOV_CLOUD_US_WEST_1, {AWS_REGION_GOV_CLOUD_US_EAST_1}) + ] + + @mock_aws + def test_aws_provider_assumes_the_role_where_validation_got_an_answer( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + # Out of the partition, so the first candidate is botocore's, not this one + monkeypatch.setenv("AWS_DEFAULT_REGION", AWS_REGION_US_EAST_1) + role_arn = ( + f"arn:{AWS_GOV_CLOUD_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:role/test-role" + ) + answered = AWSCallerIdentity( + user_id="test-user-id", + account=AWS_ACCOUNT_NUMBER, + arn=ARN(AWS_GOV_CLOUD_ACCOUNT_ARN), + region=AWS_REGION_GOV_CLOUD_US_WEST_1, + ) + + with patch( + "prowler.providers.aws.aws_provider.AwsProvider.validate_credentials", + return_value=answered, + ): + aws_provider = AwsProvider(role_arn=role_arn, session_duration=900) + + assert ( + aws_provider._assumed_role_configuration.info.sts_region + == AWS_REGION_GOV_CLOUD_US_WEST_1 + ) + + @mock_aws + def test_aws_provider_assumes_the_organizations_role_where_validation_got_an_answer( + self, monkeypatch + ): + monkeypatch.setenv("PROWLER_AWS_PARTITION", AWS_GOV_CLOUD_PARTITION) + monkeypatch.setenv("AWS_DEFAULT_REGION", AWS_REGION_US_EAST_1) + organizations_role_arn = f"arn:{AWS_GOV_CLOUD_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:role/organizations-role" + answered = AWSCallerIdentity( + user_id="test-user-id", + account=AWS_ACCOUNT_NUMBER, + arn=ARN(AWS_GOV_CLOUD_ACCOUNT_ARN), + region=AWS_REGION_GOV_CLOUD_US_WEST_1, + ) + sts_regions = [] + + class RoleAssumed(Exception): + pass + + # Stops at the assumption: the region it was handed is all this checks + def assume_role(session, assumed_role_info): + sts_regions.append(assumed_role_info.sts_region) + raise RoleAssumed + + with ( + patch( + "prowler.providers.aws.aws_provider.AwsProvider.validate_credentials", + return_value=answered, + ), + patch( + "prowler.providers.aws.aws_provider.AwsProvider.assume_role", + side_effect=assume_role, + ), + ): + with raises(RoleAssumed): + AwsProvider( + organizations_role_arn=organizations_role_arn, + session_duration=900, + ) + + assert sts_regions == [AWS_REGION_GOV_CLOUD_US_WEST_1] + @mock_aws def test_test_connection_with_env_credentials(self, monkeypatch): # Create a mock IAM user From 75c22df63b2107f04c6d80de325147feec375149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 16 Sep 2026 09:25:08 +0200 Subject: [PATCH 63/77] fix(azure): use the selected cloud endpoints in Defender and Key Vault (#12813) --- ...ign-cloud-defender-keyvault-hosts.fixed.md | 1 + .../providers/azure/lib/service/service.py | 1 + prowler/providers/azure/models.py | 4 +- .../services/defender/defender_service.py | 13 ++- .../services/keyvault/keyvault_service.py | 27 +++++- .../azure/lib/service/azure_service_test.py | 16 ++++ .../defender/defender_service_test.py | 51 +++++++++++ .../keyvault/keyvault_service_test.py | 84 +++++++++++++++++++ 8 files changed, 190 insertions(+), 7 deletions(-) create mode 100644 prowler/changelog.d/azure-sovereign-cloud-defender-keyvault-hosts.fixed.md diff --git a/prowler/changelog.d/azure-sovereign-cloud-defender-keyvault-hosts.fixed.md b/prowler/changelog.d/azure-sovereign-cloud-defender-keyvault-hosts.fixed.md new file mode 100644 index 0000000000..99ef3354e0 --- /dev/null +++ b/prowler/changelog.d/azure-sovereign-cloud-defender-keyvault-hosts.fixed.md @@ -0,0 +1 @@ +Azure Defender security contacts and Key Vault key rotation policies now use the endpoints of the selected cloud (`--azure-region`) instead of the hardcoded `management.azure.com` and `vault.azure.net` hosts, so both work on `AzureUSGovernment` and `AzureChinaCloud` diff --git a/prowler/providers/azure/lib/service/service.py b/prowler/providers/azure/lib/service/service.py index 9d63639e94..9647723173 100644 --- a/prowler/providers/azure/lib/service/service.py +++ b/prowler/providers/azure/lib/service/service.py @@ -27,6 +27,7 @@ class AzureService: ) self.subscriptions = provider.identity.subscriptions + self.region_config = provider.region_config self.resource_groups = provider.resource_groups self.locations = provider.locations self.audit_config = provider.audit_config diff --git a/prowler/providers/azure/models.py b/prowler/providers/azure/models.py index 62d03db365..5df80afab6 100644 --- a/prowler/providers/azure/models.py +++ b/prowler/providers/azure/models.py @@ -18,8 +18,8 @@ class AzureIdentityInfo(BaseModel): class AzureRegionConfig(BaseModel): name: str = "" authority: Optional[str] = None - base_url: str = "" - credential_scopes: list = [] + base_url: str = "https://management.azure.com" + credential_scopes: list = ["https://management.azure.com/.default"] graph_host: str = "https://graph.microsoft.com" graph_scope: str = "https://graph.microsoft.com/.default" logs_endpoint: str = "https://api.loganalytics.io" diff --git a/prowler/providers/azure/services/defender/defender_service.py b/prowler/providers/azure/services/defender/defender_service.py index d68d88dc22..17777843e4 100644 --- a/prowler/providers/azure/services/defender/defender_service.py +++ b/prowler/providers/azure/services/defender/defender_service.py @@ -12,7 +12,16 @@ from prowler.providers.azure.lib.service.service import AzureService class Defender(AzureService): + """Microsoft Defender for Cloud service: pricings, settings, assessments, + security contacts, IoT solutions and JIT policies per subscription.""" + def __init__(self, provider: AzureProvider): + """Collect the Defender configuration of every audited subscription. + + Args: + provider: Azure provider supplying the session, subscriptions and + the region config whose endpoints are used for every call. + """ super().__init__(SecurityCenter, provider) self.pricings = self._get_pricings() @@ -21,7 +30,7 @@ class Defender(AzureService): self.settings = self._get_settings() self.security_contact_configurations = self._get_security_contacts( token=provider.session.get_token( - "https://management.azure.com/.default" + *self.region_config.credential_scopes ).token ) self.iot_security_solutions = self._get_iot_security_solutions() @@ -168,7 +177,7 @@ class Defender(AzureService): security_contacts = {} for subscription_id, display_name in self.subscriptions.items(): try: - url = f"https://management.azure.com/subscriptions/{subscription_id}/providers/Microsoft.Security/securityContacts?api-version=2023-12-01-preview" + url = f"{self.region_config.base_url}/subscriptions/{subscription_id}/providers/Microsoft.Security/securityContacts?api-version=2023-12-01-preview" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", diff --git a/prowler/providers/azure/services/keyvault/keyvault_service.py b/prowler/providers/azure/services/keyvault/keyvault_service.py index e5b2e76427..5e79412f4b 100644 --- a/prowler/providers/azure/services/keyvault/keyvault_service.py +++ b/prowler/providers/azure/services/keyvault/keyvault_service.py @@ -83,6 +83,7 @@ class KeyVault(AzureService): subscription, resource_group, keyvault_name, + getattr(keyvault_properties, "vault_uri", ""), provider, ) secrets_future = executor.submit( @@ -150,7 +151,22 @@ class KeyVault(AzureService): ) return None - def _get_keys(self, subscription, resource_group, keyvault_name, provider): + def _get_keys( + self, subscription, resource_group, keyvault_name, vault_uri, provider + ): + """Get the keys of a Key Vault, enriched with their rotation policies. + + Args: + subscription: Subscription ID the vault belongs to. + resource_group: Resource group name of the vault. + keyvault_name: Vault name, used for the management API and logs. + vault_uri: Data-plane URI of the vault as returned by ARM, valid in + any Azure cloud. When empty, rotation policies are skipped. + provider: Azure provider whose session authenticates the KeyClient. + + Returns: + A list of Key objects; rotation_policy is set when it could be read. + """ logger.info(f"KeyVault - Getting keys for {keyvault_name}...") keys = [] keys_dict = {} @@ -179,10 +195,15 @@ class KeyVault(AzureService): f"Subscription ID: {subscription} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + if not vault_uri: + logger.warning( + f"KeyVault {keyvault_name} in {subscription} -- has no vault URI, skipping key rotation policies" + ) + return keys + try: key_client = KeyClient( - vault_url=f"https://{keyvault_name}.vault.azure.net/", - # TODO: review the following line + vault_url=vault_uri, credential=provider.session, ) properties = list(key_client.list_properties_of_keys()) diff --git a/tests/providers/azure/lib/service/azure_service_test.py b/tests/providers/azure/lib/service/azure_service_test.py index 9360be85ea..49042dc476 100644 --- a/tests/providers/azure/lib/service/azure_service_test.py +++ b/tests/providers/azure/lib/service/azure_service_test.py @@ -106,3 +106,19 @@ class TestAzureServiceSovereignClouds: service.__set_clients__(identity, session, logs_service, region_config) logs_service.assert_called_once_with(credential=session, endpoint=logs_endpoint) + + +class TestAzureServiceRegionConfig: + def test_init_keeps_provider_region_config(self): + region_config = AzureRegionConfig( + name="AzureUSGovernment", + base_url="https://management.usgovcloudapi.net", + credential_scopes=["https://management.usgovcloudapi.net/.default"], + ) + provider = MagicMock() + provider.region_config = region_config + + with patch.object(AzureService, "__set_clients__", return_value={}): + service = AzureService(MagicMock(), provider) + + assert service.region_config is region_config diff --git a/tests/providers/azure/services/defender/defender_service_test.py b/tests/providers/azure/services/defender/defender_service_test.py index b50ddd26c9..d9cdb149ab 100644 --- a/tests/providers/azure/services/defender/defender_service_test.py +++ b/tests/providers/azure/services/defender/defender_service_test.py @@ -1,6 +1,7 @@ from datetime import timedelta from unittest.mock import MagicMock, patch +from prowler.providers.azure.models import AzureRegionConfig from prowler.providers.azure.services.defender.defender_service import ( Assesment, AutoProvisioningSetting, @@ -618,3 +619,53 @@ class Test_Defender_get_jit_policies: mock_client.jit_network_access_policies.list_by_resource_group.assert_called_once_with( resource_group_name="RG" ) + + +US_GOV_REGION_CONFIG = AzureRegionConfig( + name="AzureUSGovernment", + base_url="https://management.usgovcloudapi.net", + credential_scopes=["https://management.usgovcloudapi.net/.default"], +) + + +class Test_Defender_get_security_contacts_sovereign_cloud: + def _defender(self, provider): + with ( + patch(DEFENDER_INIT_PATCHES[0], return_value={}), + patch(DEFENDER_INIT_PATCHES[1], return_value={}), + patch(DEFENDER_INIT_PATCHES[2], return_value={}), + patch(DEFENDER_INIT_PATCHES[3], return_value={}), + patch(DEFENDER_INIT_PATCHES[4], return_value={}), + patch(DEFENDER_INIT_PATCHES[5], return_value={}), + patch(DEFENDER_INIT_PATCHES[6], return_value={}), + ): + return Defender(provider) + + def test_init_requests_token_for_cloud_scope(self): + provider = set_mocked_azure_provider(azure_region_config=US_GOV_REGION_CONFIG) + + self._defender(provider) + + provider.session.get_token.assert_called_once_with( + "https://management.usgovcloudapi.net/.default" + ) + + def test_get_security_contacts_uses_cloud_management_host(self): + provider = set_mocked_azure_provider(azure_region_config=US_GOV_REGION_CONFIG) + defender = self._defender(provider) + + response = MagicMock() + response.json.return_value = {"value": []} + with patch( + "prowler.providers.azure.services.defender.defender_service.requests.get", + return_value=response, + ) as mock_get: + result = defender._get_security_contacts(token="token") + + assert result == {AZURE_SUBSCRIPTION_ID: {}} + mock_get.assert_called_once() + url = mock_get.call_args.args[0] + assert url.startswith( + f"https://management.usgovcloudapi.net/subscriptions/{AZURE_SUBSCRIPTION_ID}/" + ) + assert "management.azure.com" not in url diff --git a/tests/providers/azure/services/keyvault/keyvault_service_test.py b/tests/providers/azure/services/keyvault/keyvault_service_test.py index e43b7a9fff..d52d292af3 100644 --- a/tests/providers/azure/services/keyvault/keyvault_service_test.py +++ b/tests/providers/azure/services/keyvault/keyvault_service_test.py @@ -470,3 +470,87 @@ class Test_KeyVault_get_key_vaults: mock_client.vaults.list_by_resource_group.assert_called_once_with( resource_group_name="MyRG" ) + + +class Test_KeyVault_get_keys: + def test_get_keys_builds_key_client_from_vault_uri(self): + mock_client = MagicMock() + mock_client.keys.list.return_value = [] + + mock_provider = MagicMock() + mock_provider.identity = MagicMock() + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.azure.services.monitor.monitor_service.Monitor", + new=MagicMock(), + ), + patch( + "prowler.providers.azure.services.keyvault.keyvault_service.KeyVault._get_key_vaults", + return_value={}, + ), + ): + from prowler.providers.azure.services.keyvault.keyvault_service import ( + KeyVault, + ) + + keyvault = KeyVault(set_mocked_azure_provider()) + + keyvault.clients = {AZURE_SUBSCRIPTION_ID: mock_client} + provider = set_mocked_azure_provider() + vault_uri = "https://my-vault.vault.usgovcloudapi.net/" + + with patch( + "prowler.providers.azure.services.keyvault.keyvault_service.KeyClient" + ) as mock_key_client_cls: + mock_key_client_cls.return_value.list_properties_of_keys.return_value = [] + keys = keyvault._get_keys( + AZURE_SUBSCRIPTION_ID, RESOURCE_GROUP, "my-vault", vault_uri, provider + ) + + assert keys == [] + mock_key_client_cls.assert_called_once_with( + vault_url=vault_uri, credential=provider.session + ) + + def test_get_keys_without_vault_uri_skips_rotation_policies(self): + mock_client = MagicMock() + mock_client.keys.list.return_value = [] + + mock_provider = MagicMock() + mock_provider.identity = MagicMock() + with ( + patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=mock_provider, + ), + patch( + "prowler.providers.azure.services.monitor.monitor_service.Monitor", + new=MagicMock(), + ), + patch( + "prowler.providers.azure.services.keyvault.keyvault_service.KeyVault._get_key_vaults", + return_value={}, + ), + ): + from prowler.providers.azure.services.keyvault.keyvault_service import ( + KeyVault, + ) + + keyvault = KeyVault(set_mocked_azure_provider()) + + keyvault.clients = {AZURE_SUBSCRIPTION_ID: mock_client} + provider = set_mocked_azure_provider() + + with patch( + "prowler.providers.azure.services.keyvault.keyvault_service.KeyClient" + ) as mock_key_client_cls: + keys = keyvault._get_keys( + AZURE_SUBSCRIPTION_ID, RESOURCE_GROUP, "my-vault", "", provider + ) + + assert keys == [] + mock_key_client_cls.assert_not_called() From 974f4251dd50175578e005249da3be33d9f63a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9sar=20Arroba?= <19954079+cesararroba@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:29:50 +0200 Subject: [PATCH 64/77] chore(trivy): suppress fast-uri CVE-2026-75931 from Teams SPDX manifest (#12823) --- .trivyignore.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.trivyignore.yaml b/.trivyignore.yaml index efac339352..f572065625 100644 --- a/.trivyignore.yaml +++ b/.trivyignore.yaml @@ -125,6 +125,10 @@ vulnerabilities: purls: - "pkg:npm/fast-uri" expired_at: 2027-01-31 + - id: CVE-2026-75931 + purls: + - "pkg:npm/fast-uri" + expired_at: 2027-01-31 - id: CVE-2026-69192 purls: - "pkg:npm/ip-address" From 2198ba2d84fb0dd3e85b8e705fbd6901cd3443c0 Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Wed, 16 Sep 2026 12:21:25 +0200 Subject: [PATCH 65/77] feat(ui): complete Registry provider onboarding for Private Cloud (#12494) Co-authored-by: alejandrobailo --- .github/test-impact.yml | 11 + .github/workflows/ui-e2e-tests-v2.yml | 85 +- .../developer-guide/environment-variables.mdx | 10 + ui/Dockerfile | 2 + ui/actions/auth/auth.test.ts | 28 +- ui/actions/auth/auth.ts | 69 +- .../dynamic-provider-credentials.test.ts | 180 ++ .../providers/dynamic-provider-credentials.ts | 115 + ui/actions/providers/index.ts | 1 + .../provider-schemas.adapter.test.ts | 83 + .../providers/provider-schemas.adapter.ts | 38 + ui/actions/providers/provider-schemas.test.ts | 138 ++ ui/actions/providers/provider-schemas.ts | 61 + .../providers/registry-provider.test.ts | 113 + ui/actions/providers/registry-provider.ts | 57 + ui/actions/registry/registry.adapter.test.ts | 696 ++++++ ui/actions/registry/registry.adapter.ts | 441 ++++ ui/actions/registry/registry.test.ts | 1138 +++++++++ ui/actions/registry/registry.ts | 578 +++++ ui/actions/roles/roles.test.ts | 31 + ui/actions/roles/roles.ts | 4 + ui/app/(prowler)/layout.tsx | 17 +- ui/app/(prowler)/registry/page.tsx | 26 + ui/auth.config.test.ts | 21 + ui/auth.config.ts | 1 + .../registry-private-cloud.added.md | 1 + .../app-sidebar/app-sidebar-content.test.tsx | 28 + .../app-sidebar/app-sidebar-content.tsx | 4 + .../layout/app-sidebar/navigation-config.ts | 15 + .../providers/radio-group-provider.test.tsx | 134 + .../providers/radio-group-provider.tsx | 207 +- .../providers/table/column-providers.tsx | 2 +- .../table/data-table-row-actions.test.tsx | 20 +- .../table/data-table-row-actions.tsx | 4 +- .../wizard/provider-wizard-modal.test.tsx | 230 ++ .../wizard/provider-wizard-modal.tsx | 11 +- .../providers/wizard/steps/connect-step.tsx | 1 + .../wizard/steps/credentials-step.test.tsx | 3 + .../wizard/steps/credentials-step.tsx | 20 +- .../steps/dynamic-credentials-step.test.tsx | 365 +++ .../wizard/steps/dynamic-credentials-step.tsx | 336 +++ .../providers/wizard/steps/footer-controls.ts | 1 + .../forms/connect-account-form.test.tsx | 84 + .../workflow/forms/connect-account-form.tsx | 131 +- .../provider-credential-fields.test.tsx | 136 ++ .../workflow/provider-credential-fields.tsx | 152 ++ .../registry/registry-access-dialog.tsx | 162 ++ ...egistry-artifact-card.integration.test.tsx | 236 ++ .../registry/registry-artifact-card.tsx | 410 ++++ .../registry/registry-artifact-grid.tsx | 51 + .../registry-artifact-task-handler.test.tsx | 187 ++ .../registry-artifact-task-handler.ts | 37 + .../registry/registry-credential-banner.tsx | 64 + .../registry-credential-task-handler.test.ts | 112 + .../registry-credential-task-handler.ts | 16 + .../registry-explorer.integration.test.tsx | 2170 +++++++++++++++++ .../registry/registry-explorer.model.test.ts | 273 +++ .../registry/registry-explorer.model.ts | 153 ++ ui/components/registry/registry-explorer.tsx | 741 ++++++ .../registry/registry-remove-dialog.tsx | 94 + ui/components/registry/registry-toolbar.tsx | 156 ++ .../registry/use-registry-refresh.ts | 97 + .../workflow/forms/add-role-form.test.tsx | 22 + .../roles/workflow/forms/add-role-form.tsx | 2 + .../workflow/forms/edit-role-form.test.tsx | 22 + .../roles/workflow/forms/edit-role-form.tsx | 4 + ui/components/shadcn/toast/Toast.tsx | 2 +- .../shadcn/toast/Toaster.integration.test.tsx | 66 + ui/components/shadcn/toast/Toaster.test.tsx | 3 +- ui/components/shared/task-polling-watcher.tsx | 12 + ui/hooks/use-auth.ts | 1 + ui/lib/auth/current-user.test.ts | 146 ++ ui/lib/auth/current-user.ts | 102 + ui/lib/csp.ts | 4 +- ui/lib/helper.ts | 5 + ui/lib/permissions.test.ts | 29 + ui/lib/permissions.ts | 5 + .../fixtures/openai-credential-schema.json | 24 + .../fixtures/template-credential-schema.json | 49 + .../provider-credential-schema.test.ts | 266 ++ .../provider-credential-schema.ts | 258 ++ .../provider-credential-values.test.ts | 136 ++ .../provider-credential-values.ts | 85 + ui/lib/provider-helpers.test.ts | 36 + ui/lib/provider-helpers.ts | 11 +- ui/lib/registry/access.server.test.ts | 177 ++ ui/lib/registry/access.server.ts | 61 + ui/lib/registry/access.test.ts | 18 + ui/lib/registry/access.ts | 19 + ui/lib/registry/artifact-execution.test.ts | 186 ++ ui/lib/registry/artifact-execution.ts | 122 + ui/lib/registry/artifact-notifications.tsx | 45 + ui/lib/registry/artifacts.ts | 8 + ui/lib/registry/credential-execution.test.ts | 311 +++ ui/lib/registry/credential-execution.ts | 63 + ui/lib/registry/credential-result.ts | 142 ++ ui/lib/registry/credential-task.test.ts | 20 + ui/lib/registry/credential-task.ts | 47 + ui/lib/registry/presentation.test.ts | 43 + ui/lib/registry/presentation.ts | 33 + ui/lib/registry/provider-options.test.ts | 120 + ui/lib/registry/provider-options.ts | 56 + ui/lib/role-permissions.ts | 1 + ui/next.config.js | 2 + ui/next.config.test.ts | 11 + ui/package.json | 1 + ui/playwright.base.ts | 24 + ui/playwright.config.ts | 29 +- ui/playwright.registry.config.ts | 93 + ui/proxy.registry.test.ts | 38 + ui/proxy.test.ts | 3 + ui/proxy.ts | 17 +- ui/store/task-watcher/store.test.ts | 174 ++ ui/store/task-watcher/store.ts | 117 +- ui/store/ui/store-initializer.test.tsx | 36 + ui/store/ui/store-initializer.tsx | 12 +- ui/store/ui/store.ts | 11 + ui/tests/providers/providers-page.ts | 9 + ui/tests/providers/providers.md | 13 +- ui/tests/providers/providers.spec.ts | 3 +- ui/tests/registry/add-provider-tour-report.md | 16 + ui/tests/registry/controlled-registry-api.mts | 852 +++++++ .../registry/controlled-registry-fixture.ts | 89 + .../registry-catalog-desktop-dark.png | Bin 0 -> 133227 bytes .../registry-catalog-desktop-light.png | Bin 0 -> 136335 bytes .../evidence/registry-catalog-mobile-dark.png | Bin 0 -> 163686 bytes .../registry-catalog-tablet-light.png | Bin 0 -> 82812 bytes .../registry-provider-credentials.png | Bin 0 -> 84649 bytes .../registry-provider-scan-completed.png | Bin 0 -> 103799 bytes .../evidence/registry-provider-selector.png | Bin 0 -> 103904 bytes ui/tests/registry/registry-page.ts | 310 +++ ui/tests/registry/registry.md | 114 + ui/tests/registry/registry.spec.ts | 492 ++++ ui/tests/registry/validation.md | 69 + ui/tests/setups/manage-registry.auth.setup.ts | 30 + ui/types/dynamic-provider-form.test.ts | 28 + ui/types/env.d.ts | 2 + ui/types/formSchemas.test.ts | 25 + ui/types/formSchemas.ts | 24 +- ui/types/provider-schema.ts | 33 + ui/types/registry.ts | 290 +++ ui/types/users.ts | 2 + ui/vitest.config.ts | 6 +- ui/vitest.integration.setup.ts | 4 + 144 files changed, 16218 insertions(+), 311 deletions(-) create mode 100644 ui/actions/providers/dynamic-provider-credentials.test.ts create mode 100644 ui/actions/providers/dynamic-provider-credentials.ts create mode 100644 ui/actions/providers/provider-schemas.adapter.test.ts create mode 100644 ui/actions/providers/provider-schemas.adapter.ts create mode 100644 ui/actions/providers/provider-schemas.test.ts create mode 100644 ui/actions/providers/provider-schemas.ts create mode 100644 ui/actions/providers/registry-provider.test.ts create mode 100644 ui/actions/providers/registry-provider.ts create mode 100644 ui/actions/registry/registry.adapter.test.ts create mode 100644 ui/actions/registry/registry.adapter.ts create mode 100644 ui/actions/registry/registry.test.ts create mode 100644 ui/actions/registry/registry.ts create mode 100644 ui/app/(prowler)/registry/page.tsx create mode 100644 ui/changelog.d/registry-private-cloud.added.md create mode 100644 ui/components/providers/radio-group-provider.test.tsx create mode 100644 ui/components/providers/wizard/provider-wizard-modal.test.tsx create mode 100644 ui/components/providers/wizard/steps/dynamic-credentials-step.test.tsx create mode 100644 ui/components/providers/wizard/steps/dynamic-credentials-step.tsx create mode 100644 ui/components/providers/workflow/forms/connect-account-form.test.tsx create mode 100644 ui/components/providers/workflow/provider-credential-fields.test.tsx create mode 100644 ui/components/providers/workflow/provider-credential-fields.tsx create mode 100644 ui/components/registry/registry-access-dialog.tsx create mode 100644 ui/components/registry/registry-artifact-card.integration.test.tsx create mode 100644 ui/components/registry/registry-artifact-card.tsx create mode 100644 ui/components/registry/registry-artifact-grid.tsx create mode 100644 ui/components/registry/registry-artifact-task-handler.test.tsx create mode 100644 ui/components/registry/registry-artifact-task-handler.ts create mode 100644 ui/components/registry/registry-credential-banner.tsx create mode 100644 ui/components/registry/registry-credential-task-handler.test.ts create mode 100644 ui/components/registry/registry-credential-task-handler.ts create mode 100644 ui/components/registry/registry-explorer.integration.test.tsx create mode 100644 ui/components/registry/registry-explorer.model.test.ts create mode 100644 ui/components/registry/registry-explorer.model.ts create mode 100644 ui/components/registry/registry-explorer.tsx create mode 100644 ui/components/registry/registry-remove-dialog.tsx create mode 100644 ui/components/registry/registry-toolbar.tsx create mode 100644 ui/components/registry/use-registry-refresh.ts create mode 100644 ui/components/shadcn/toast/Toaster.integration.test.tsx create mode 100644 ui/lib/auth/current-user.test.ts create mode 100644 ui/lib/auth/current-user.ts create mode 100644 ui/lib/provider-credentials/fixtures/openai-credential-schema.json create mode 100644 ui/lib/provider-credentials/fixtures/template-credential-schema.json create mode 100644 ui/lib/provider-credentials/provider-credential-schema.test.ts create mode 100644 ui/lib/provider-credentials/provider-credential-schema.ts create mode 100644 ui/lib/provider-credentials/provider-credential-values.test.ts create mode 100644 ui/lib/provider-credentials/provider-credential-values.ts create mode 100644 ui/lib/provider-helpers.test.ts create mode 100644 ui/lib/registry/access.server.test.ts create mode 100644 ui/lib/registry/access.server.ts create mode 100644 ui/lib/registry/access.test.ts create mode 100644 ui/lib/registry/access.ts create mode 100644 ui/lib/registry/artifact-execution.test.ts create mode 100644 ui/lib/registry/artifact-execution.ts create mode 100644 ui/lib/registry/artifact-notifications.tsx create mode 100644 ui/lib/registry/artifacts.ts create mode 100644 ui/lib/registry/credential-execution.test.ts create mode 100644 ui/lib/registry/credential-execution.ts create mode 100644 ui/lib/registry/credential-result.ts create mode 100644 ui/lib/registry/credential-task.test.ts create mode 100644 ui/lib/registry/credential-task.ts create mode 100644 ui/lib/registry/presentation.test.ts create mode 100644 ui/lib/registry/presentation.ts create mode 100644 ui/lib/registry/provider-options.test.ts create mode 100644 ui/lib/registry/provider-options.ts create mode 100644 ui/playwright.base.ts create mode 100644 ui/playwright.registry.config.ts create mode 100644 ui/proxy.registry.test.ts create mode 100644 ui/store/ui/store-initializer.test.tsx create mode 100644 ui/tests/registry/add-provider-tour-report.md create mode 100644 ui/tests/registry/controlled-registry-api.mts create mode 100644 ui/tests/registry/controlled-registry-fixture.ts create mode 100644 ui/tests/registry/evidence/registry-catalog-desktop-dark.png create mode 100644 ui/tests/registry/evidence/registry-catalog-desktop-light.png create mode 100644 ui/tests/registry/evidence/registry-catalog-mobile-dark.png create mode 100644 ui/tests/registry/evidence/registry-catalog-tablet-light.png create mode 100644 ui/tests/registry/evidence/registry-provider-credentials.png create mode 100644 ui/tests/registry/evidence/registry-provider-scan-completed.png create mode 100644 ui/tests/registry/evidence/registry-provider-selector.png create mode 100644 ui/tests/registry/registry-page.ts create mode 100644 ui/tests/registry/registry.md create mode 100644 ui/tests/registry/registry.spec.ts create mode 100644 ui/tests/registry/validation.md create mode 100644 ui/tests/setups/manage-registry.auth.setup.ts create mode 100644 ui/types/dynamic-provider-form.test.ts create mode 100644 ui/types/provider-schema.ts create mode 100644 ui/types/registry.ts diff --git a/.github/test-impact.yml b/.github/test-impact.yml index 874e9eba50..67c106d58b 100644 --- a/.github/test-impact.yml +++ b/.github/test-impact.yml @@ -451,6 +451,17 @@ modules: e2e: - ui/tests/home/** + - name: ui-registry + match: + - ui/actions/registry/** + - ui/app/**/registry/** + - ui/components/registry/** + - ui/lib/registry/** + - ui/tests/registry/** + tests: [] + e2e: + - ui/tests/registry/** + - name: ui-shadcn match: - ui/components/shadcn/** diff --git a/.github/workflows/ui-e2e-tests-v2.yml b/.github/workflows/ui-e2e-tests-v2.yml index 2a384597c3..2bf6db8a5a 100644 --- a/.github/workflows/ui-e2e-tests-v2.yml +++ b/.github/workflows/ui-e2e-tests-v2.yml @@ -10,12 +10,12 @@ on: - master - "v5.*" paths: - - '.github/workflows/ui-e2e-tests-v2.yml' - - '.github/test-impact.yml' - - 'ui/**' - - 'api/**' # API changes can affect UI E2E - - '!ui/CHANGELOG.md' - - '!api/CHANGELOG.md' + - ".github/workflows/ui-e2e-tests-v2.yml" + - ".github/test-impact.yml" + - "ui/**" + - "api/**" # API changes can affect UI E2E + - "!ui/CHANGELOG.md" + - "!api/CHANGELOG.md" concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} @@ -40,11 +40,11 @@ jobs: (needs.impact-analysis.outputs.has-ui-e2e == 'true' || needs.impact-analysis.outputs.run-all == 'true') runs-on: ubuntu-latest env: - AUTH_SECRET: 'fallback-ci-secret-for-testing' + AUTH_SECRET: "fallback-ci-secret-for-testing" AUTH_TRUST_HOST: true - NEXTAUTH_URL: 'http://localhost:3000' - AUTH_URL: 'http://localhost:3000' - UI_API_BASE_URL: 'http://localhost:8080/api/v1' + NEXTAUTH_URL: "http://localhost:3000" + AUTH_URL: "http://localhost:3000" + UI_API_BASE_URL: "http://localhost:8080/api/v1" E2E_ADMIN_USER: ${{ secrets.E2E_ADMIN_USER }} E2E_ADMIN_PASSWORD: ${{ secrets.E2E_ADMIN_PASSWORD }} E2E_AWS_PROVIDER_ACCOUNT_ID: ${{ secrets.E2E_AWS_PROVIDER_ACCOUNT_ID }} @@ -60,7 +60,7 @@ jobs: E2E_M365_SECRET_ID: ${{ secrets.E2E_M365_SECRET_ID }} E2E_M365_TENANT_ID: ${{ secrets.E2E_M365_TENANT_ID }} E2E_M365_CERTIFICATE_CONTENT: ${{ secrets.E2E_M365_CERTIFICATE_CONTENT }} - E2E_KUBERNETES_CONTEXT: 'kind-kind' + E2E_KUBERNETES_CONTEXT: "kind-kind" E2E_KUBERNETES_KUBECONFIG_PATH: /home/runner/.kube/config E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY: ${{ secrets.E2E_GCP_BASE64_SERVICE_ACCOUNT_KEY }} E2E_GCP_PROJECT_ID: ${{ secrets.E2E_GCP_PROJECT_ID }} @@ -292,7 +292,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 with: - node-version-file: 'ui/.nvmrc' + node-version-file: "ui/.nvmrc" - name: Setup pnpm uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0 @@ -337,60 +337,59 @@ jobs: if: steps.playwright-cache.outputs.cache-hit != 'true' run: pnpm run test:e2e:install - - name: Run E2E tests + - name: Run standard E2E tests + id: standard-e2e working-directory: ./ui run: | if [[ "${RUN_ALL_TESTS}" == "true" ]]; then - echo "Running ALL E2E tests..." + echo "Running all standard E2E tests..." pnpm run test:e2e else - echo "Running targeted E2E tests: ${E2E_TEST_PATHS}" - # Convert glob patterns to playwright test paths - # e.g., "ui/tests/providers/**" -> "tests/providers" + echo "Running targeted standard E2E tests: ${E2E_TEST_PATHS}" TEST_PATHS="${E2E_TEST_PATHS}" - # Remove ui/ prefix and convert ** to empty (playwright handles recursion) TEST_PATHS=$(echo "$TEST_PATHS" | sed 's|ui/||g' | sed 's|\*\*||g' | tr ' ' '\n' | sort -u) - # Drop auth setup helpers (not runnable test suites) - TEST_PATHS=$(echo "$TEST_PATHS" | grep -v '^tests/setups/') - # Safety net: if bare "tests/" appears (from broad patterns like ui/tests/**), - # expand to specific subdirs to avoid Playwright discovering setup files + TEST_PATHS=$(echo "$TEST_PATHS" | grep -vE '^tests/(setups|registry)/' || true) + if echo "$TEST_PATHS" | grep -qx 'tests/'; then - echo "Expanding bare 'tests/' to specific subdirs (excluding setups)..." SPECIFIC_DIRS="" for dir in tests/*/; do - [[ "$dir" == "tests/setups/" ]] && continue + [[ "$dir" == "tests/setups/" || "$dir" == "tests/registry/" ]] && continue SPECIFIC_DIRS="${SPECIFIC_DIRS}${dir}"$'\n' done - # Replace "tests/" with specific dirs, keep other paths - TEST_PATHS=$(echo "$TEST_PATHS" | grep -vx 'tests/') + TEST_PATHS=$(echo "$TEST_PATHS" | grep -vx 'tests/' || true) TEST_PATHS="${TEST_PATHS}"$'\n'"${SPECIFIC_DIRS}" TEST_PATHS=$(echo "$TEST_PATHS" | grep -v '^$' | sort -u) fi - if [[ -z "$TEST_PATHS" ]]; then - echo "No runnable E2E test paths after filtering setups" - exit 0 - fi - # Filter out directories that don't contain any test files + VALID_PATHS="" - while IFS= read -r p; do - [[ -z "$p" ]] && continue - if find "$p" -name '*.spec.ts' -o -name '*.test.ts' 2>/dev/null | head -1 | grep -q .; then - VALID_PATHS="${VALID_PATHS}${p}"$'\n' + while IFS= read -r path; do + [[ -z "$path" ]] && continue + if find "$path" -name '*.spec.ts' -o -name '*.test.ts' 2>/dev/null | head -1 | grep -q .; then + VALID_PATHS="${VALID_PATHS}${path}"$'\n' else - echo "Skipping empty test directory: $p" + echo "Skipping empty test directory: $path" fi done <<< "$TEST_PATHS" VALID_PATHS=$(echo "$VALID_PATHS" | grep -v '^$' || true) - if [[ -z "$VALID_PATHS" ]]; then - echo "No test files found in any resolved paths — skipping E2E" - exit 0 + + if [[ -n "$VALID_PATHS" ]]; then + TEST_PATHS=$(echo "$VALID_PATHS" | tr '\n' ' ') + echo "Resolved standard test paths: $TEST_PATHS" + read -ra test_paths <<< "$TEST_PATHS" + pnpm exec playwright test "${test_paths[@]}" + else + echo "No standard E2E test paths selected." fi - TEST_PATHS=$(echo "$VALID_PATHS" | tr '\n' ' ') - echo "Resolved test paths: $TEST_PATHS" - read -ra test_paths <<< "$TEST_PATHS" - pnpm exec playwright test "${test_paths[@]}" fi + - name: Run Registry fixture E2E tests + if: | + !cancelled() && + (steps.standard-e2e.outcome == 'success' || steps.standard-e2e.outcome == 'failure') && + (env.RUN_ALL_TESTS == 'true' || contains(format(' {0} ', env.E2E_TEST_PATHS), ' ui/tests/registry/')) + working-directory: ./ui + run: pnpm run test:e2e:registry + - name: Upload test reports uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 if: failure() diff --git a/docs/developer-guide/environment-variables.mdx b/docs/developer-guide/environment-variables.mdx index e2bec0f94b..a6ba5c9d54 100644 --- a/docs/developer-guide/environment-variables.mdx +++ b/docs/developer-guide/environment-variables.mdx @@ -40,6 +40,16 @@ The former build-time variables map to the new runtime variables as follows: `UI_CLOUD_ENABLED` is a plain runtime boolean flag that enables Prowler Cloud behavior when set to the exact string `"true"` and defaults to off; unlike the other renamed variables it has no legacy fallback, so `NEXT_PUBLIC_IS_CLOUD_ENV` is no longer read. +## Registry UI Rollout and Rollback + +`UI_REGISTRY_ENABLED` is an optional runtime flag for Prowler Cloud and Private Cloud. Registry is eligible only when both `UI_CLOUD_ENABLED` and `UI_REGISTRY_ENABLED` are the exact string `"true"` and the current user has the backend-authorized `manage_registry` permission. Unset, `"false"`, or malformed values fail closed. The flag defaults to off and is not a replacement for backend authorization. Registry access is independent of billing; Private Cloud can use it with `CLOUD_BILLING_ENABLED=false`. + +Roll out Registry only after the Registry backend dependency is deployed, intended roles have `manage_registry`, and acceptance with real credentials has exercised installation, provider account creation, credentials, connection, and scan launch. Deploy the UI with `UI_REGISTRY_ENABLED` unset or `"false"`; set it to `"true"` only in the prepared process environment, then restart or otherwise apply the environment update required by the platform. A Registry key must belong to the configured Registry environment; a production key does not authenticate against a development Registry. + +The catalog displays all artifacts, including built-ins and packages containing only checks or compliance frameworks. Only external provider artifacts support Add. After confirmed installation, open Providers and select the option labeled Registry to configure an account. Creating accounts and running scans also require the corresponding provider and scan permissions. Removing an artifact keeps existing provider accounts, but future connections or scans can fail until the artifact is installed again. + +To roll back, set `UI_REGISTRY_ENABLED=false` or remove it and apply the environment update. Proxy, page, and action checks deny on their next request. Navigation refreshes from server-authorized access when the page is requested again. Rollback does not delete Registry credentials, tenant artifact records, or provider accounts. + The build-time-only Sentry variables used for source-map upload — `SENTRY_ORG`, `SENTRY_PROJECT`, `SENTRY_AUTH_TOKEN`, and `SENTRY_RELEASE` — keep their names, as they are not part of Prowler Local Server's runtime configuration. ## Enabling Third-Party Integrations diff --git a/ui/Dockerfile b/ui/Dockerfile index a7ff72e65f..278c8b8602 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -100,6 +100,8 @@ ENV HOSTNAME="0.0.0.0" # - required: UI_API_BASE_URL, AUTH_URL, AUTH_SECRET (missing ⇒ fail fast at boot) # - optional: UI_API_DOCS_URL # - optional: UI_CLOUD_ENABLED ("true" only in Prowler Cloud deployments) +# - optional: UI_REGISTRY_ENABLED ("true" only after the Registry dependency, +# Cloud role grant, and controlled acceptance are ready; unset/false hides Registry) # - gated integrations (load only when *_ENABLED="true"; the value is then # required or boot fails). Their legacy names (NEXT_PUBLIC_SENTRY_*, # NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID, POSTHOG_KEY/HOST) still work: diff --git a/ui/actions/auth/auth.test.ts b/ui/actions/auth/auth.test.ts index 1f20392bb8..adf04ebcf1 100644 --- a/ui/actions/auth/auth.test.ts +++ b/ui/actions/auth/auth.test.ts @@ -23,7 +23,7 @@ vi.mock("@/lib/sentry-breadcrumbs", () => ({ import { createNewUser, getUserByMe } from "./auth"; -const userMeResponse = (roleAttributes: Record) => ({ +const userMeResponse = (roleAttributes: Record) => ({ data: { type: "users", id: "019b1234-5678-7abc-9def-0123456789ab", @@ -43,7 +43,7 @@ const userMeResponse = (roleAttributes: Record) => ({ ], }); -const mockUserMe = (roleAttributes: Record) => { +const mockUserMe = (roleAttributes: Record) => { fetchMock.mockResolvedValue( new Response(JSON.stringify(userMeResponse(roleAttributes)), { status: 200, @@ -178,6 +178,30 @@ describe("auth actions", () => { expect(result.permissions.manage_users).toBe(true); }); + it("should carry an exact manage_registry permission into the session", async () => { + // Given + mockUserMe({ manage_registry: true }); + + // When + const result = await getUserByMe("access-token"); + + // Then + expect(result.permissions.manage_registry).toBe(true); + }); + + it.each([undefined, "true", "TRUE", 1])( + "should deny a malformed manage_registry value of %j", + async (manageRegistry) => { + // Given + mockUserMe({ manage_registry: manageRegistry }); + + // When + const result = await getUserByMe("access-token"); + + // Then + expect(result.permissions.manage_registry).toBe(false); + }, + ); it("should forward an abort signal when loading the current user", async () => { // Given mockUserMe({ manage_users: true }); diff --git a/ui/actions/auth/auth.ts b/ui/actions/auth/auth.ts index 6d275bbf92..0cd5df4d94 100644 --- a/ui/actions/auth/auth.ts +++ b/ui/actions/auth/auth.ts @@ -4,7 +4,7 @@ import { AuthError } from "next-auth"; import { signIn, signOut } from "@/auth.config"; import { apiBaseUrl } from "@/lib"; -import { UserMeError } from "@/lib/auth-errors"; +import { fetchCurrentUser } from "@/lib/auth/current-user"; import { addAuthEvent } from "@/lib/sentry-breadcrumbs"; import type { UtmParams } from "@/lib/utm"; import type { SignInFormData, SignUpFormData } from "@/types"; @@ -145,66 +145,15 @@ export const getUserByMe = async ( accessToken: string, signal?: AbortSignal, ) => { - const url = new URL(`${apiBaseUrl}/users/me?include=roles`); + const currentUser = await fetchCurrentUser(accessToken, { signal }); - try { - const response = await fetch(url.toString(), { - method: "GET", - headers: { - Accept: "application/vnd.api+json", - Authorization: `Bearer ${accessToken}`, - }, - signal, - }); - - if (!response.ok) { - const errorMessage = - response.status === 401 - ? "Invalid or expired token" - : response.status === 403 - ? "Access denied" - : response.status === 404 - ? "User not found" - : "Unable to load user"; - throw new UserMeError(errorMessage, response.status); - } - - const parsedResponse = await response.json(); - - const userRole = parsedResponse.included?.find( - (item: any) => item.type === "roles", - ); - - const permissions = { - manage_users: userRole.attributes.manage_users || false, - manage_account: userRole.attributes.manage_account || false, - manage_providers: userRole.attributes.manage_providers || false, - manage_scans: userRole.attributes.manage_scans || false, - manage_ingestions: userRole.attributes.manage_ingestions || false, - manage_integrations: userRole.attributes.manage_integrations || false, - manage_billing: userRole.attributes.manage_billing || false, - manage_alerts: userRole.attributes.manage_alerts || false, - manage_lighthouse_ai_configuration: - userRole.attributes.manage_lighthouse_ai_configuration || false, - unlimited_visibility: userRole.attributes.unlimited_visibility || false, - }; - - return { - name: parsedResponse.data.attributes.name, - email: parsedResponse.data.attributes.email, - company: parsedResponse.data.attributes.company_name, - dateJoined: parsedResponse.data.attributes.date_joined, - permissions, - }; - } catch (error: unknown) { - if (error instanceof UserMeError) throw error; - - throw new UserMeError( - error instanceof Error - ? error.message - : "Network error or server unreachable", - ); - } + return { + name: currentUser.name, + email: currentUser.email, + company: currentUser.company, + dateJoined: currentUser.dateJoined, + permissions: currentUser.permissions, + }; }; export async function logOut() { diff --git a/ui/actions/providers/dynamic-provider-credentials.test.ts b/ui/actions/providers/dynamic-provider-credentials.test.ts new file mode 100644 index 0000000000..f8ab619bc8 --- /dev/null +++ b/ui/actions/providers/dynamic-provider-credentials.test.ts @@ -0,0 +1,180 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import openaiSchema from "@/lib/provider-credentials/fixtures/openai-credential-schema.json"; +import templateSchema from "@/lib/provider-credentials/fixtures/template-credential-schema.json"; +const { fetchMock, getProviderSchemas, getAuthHeaders, revalidatePath } = + vi.hoisted(() => ({ + fetchMock: vi.fn(), + getProviderSchemas: vi.fn(), + getAuthHeaders: vi.fn(), + revalidatePath: vi.fn(), + })); +vi.mock("@/lib", () => ({ + apiBaseUrl: "https://api.test/api/v1", + getAuthHeaders, +})); +vi.mock("next/cache", () => ({ revalidatePath })); +vi.mock("./provider-schemas", () => ({ getProviderSchemas })); + +import { saveDynamicProviderCredentials } from "./dynamic-provider-credentials"; + +const input = { + providerId: "account", + secretType: "api_key", + secret: { token: "private-value" }, +}; +const response = (body: unknown, status = 200) => + new Response(JSON.stringify(body), { status }); +const account = (secretId: string | null = null) => ({ + data: { + id: "account", + attributes: { provider: "acme" }, + relationships: { secret: { data: secretId ? { id: secretId } : null } }, + }, +}); + +describe("dynamic provider credential actions", () => { + beforeEach(() => { + vi.stubGlobal("fetch", fetchMock); + fetchMock.mockReset(); + getAuthHeaders.mockResolvedValue({ Authorization: "Bearer test" }); + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "acme", + secretTypes: { + api_key: { + type: "object", + description: openaiSchema.description, + properties: { + token: { type: "string", format: "password", writeOnly: true }, + }, + required: ["token"], + }, + }, + }); + }); + it("validates the account's current schema and sends JSON credentials without the builtin mapping", async () => { + fetchMock + .mockResolvedValueOnce(response(account())) + .mockResolvedValueOnce(response({ data: { id: "saved" } }, 201)); + expect(await saveDynamicProviderCredentials(input)).toEqual({ + status: "saved", + secretId: "saved", + }); + expect(getProviderSchemas).toHaveBeenCalledWith("acme"); + const [url, request] = fetchMock.mock.calls[1]; + expect(url).toBe("https://api.test/api/v1/providers/secrets"); + expect(JSON.parse(request.body).data).toEqual({ + type: "provider-secrets", + attributes: { + secret_type: "api_key", + secret: { token: "private-value" }, + }, + relationships: { + provider: { data: { id: "account", type: "providers" } }, + }, + }); + }); + it("updates the authoritative existing secret, including after a retry", async () => { + fetchMock + .mockResolvedValueOnce(response(account("existing"))) + .mockResolvedValueOnce(response({ data: { id: "existing" } })); + expect((await saveDynamicProviderCredentials(input)).status).toBe("saved"); + expect( + fetchMock.mock.calls[1][0].endsWith("/providers/secrets/existing"), + ).toBe(true); + expect(fetchMock.mock.calls[1][1].method).toBe("PATCH"); + }); + it("validates and sends Template credentials with their JSON types", async () => { + // Given + const templateAccount = account(); + templateAccount.data.attributes.provider = "template"; + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "template", + secretTypes: { static: templateSchema }, + }); + fetchMock + .mockResolvedValueOnce(response(templateAccount)) + .mockResolvedValueOnce(response({ data: { id: "saved" } }, 201)); + const secret = { + api_url: "https://api.example.test", + api_key: "fixture-key-not-a-secret", + verify_tls: false, + timeout_seconds: 60, + }; + + // When / Then + expect( + await saveDynamicProviderCredentials({ + ...input, + secretType: "static", + secret, + }), + ).toEqual({ + status: "saved", + secretId: "saved", + }); + expect(JSON.parse(fetchMock.mock.calls[1][1].body).data.attributes).toEqual( + { + secret_type: "static", + secret, + }, + ); + + // Server-side validation also rejects requests that bypass the form. + fetchMock.mockReset().mockResolvedValueOnce(response(templateAccount)); + expect( + await saveDynamicProviderCredentials({ + ...input, + secretType: "static", + secret: { ...secret, timeout_seconds: 301 }, + }), + ).toMatchObject({ + status: "invalid", + errors: { timeout_seconds: expect.any(String) }, + }); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + it.each([ + { ...input, secretType: "invented" }, + { ...input, secret: { token: "" } }, + { ...input, secret: { token: "x", unknown: "hidden" } }, + ])("does not write invalid credentials", async (values) => { + fetchMock.mockResolvedValueOnce(response(account())); + expect((await saveDynamicProviderCredentials(values)).status).not.toBe( + "saved", + ); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + it("fails closed for an absent schema, revoked permission, and malformed accounts", async () => { + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "acme", + secretTypes: {}, + }); + fetchMock.mockResolvedValueOnce(response(account())); + expect((await saveDynamicProviderCredentials(input)).status).toBe( + "schema_unavailable", + ); + fetchMock.mockResolvedValueOnce(response({}, 403)); + expect((await saveDynamicProviderCredentials(input)).status).toBe( + "access_denied", + ); + fetchMock.mockResolvedValueOnce(response({})); + expect((await saveDynamicProviderCredentials(input)).status).toBe("error"); + expect(fetchMock.mock.calls.every(([, options]) => !options.method)).toBe( + true, + ); + }); + it("does not echo a rejected secret in errors", async () => { + fetchMock + .mockResolvedValueOnce(response(account())) + .mockResolvedValueOnce( + response({ errors: [{ detail: "private-value invalid" }] }, 400), + ); + expect( + JSON.stringify(await saveDynamicProviderCredentials(input)), + ).not.toContain("private-value"); + }); +}); diff --git a/ui/actions/providers/dynamic-provider-credentials.ts b/ui/actions/providers/dynamic-provider-credentials.ts new file mode 100644 index 0000000000..79975fa2e7 --- /dev/null +++ b/ui/actions/providers/dynamic-provider-credentials.ts @@ -0,0 +1,115 @@ +"use server"; + +import { revalidatePath } from "next/cache"; +import { z } from "zod"; + +import { apiBaseUrl, getAuthHeaders } from "@/lib"; +import { parseRegistryCredentialSchema } from "@/lib/provider-credentials/provider-credential-schema"; +import { validateCredentialValues } from "@/lib/provider-credentials/provider-credential-values"; +import { isKnownProviderType } from "@/types/providers"; + +import { getProviderSchemas } from "./provider-schemas"; + +const resourceId = z.string().regex(/^[a-zA-Z0-9_-]{1,100}$/); +const inputSchema = z.object({ + providerId: resourceId, + secretType: z.string().min(1), + secret: z.unknown(), +}); +const accountSchema = z.object({ + data: z.object({ + id: resourceId, + attributes: z.object({ provider: z.string() }), + relationships: z.object({ + secret: z.object({ data: z.object({ id: resourceId }).nullable() }), + }), + }), +}); + +export type DynamicCredentialsResult = + | { status: "saved"; secretId: string } + | { status: "invalid"; errors: Record } + | { status: "access_denied" | "schema_unavailable" | "error" }; + +export async function saveDynamicProviderCredentials( + input: unknown, +): Promise { + const parsed = inputSchema.safeParse(input); + if (!parsed.success) + return { + status: "invalid", + errors: { _form: "Check the provider and credential fields." }, + }; + const { providerId, secretType, secret } = parsed.data; + try { + const headers = await getAuthHeaders({ contentType: true }); + const accountResponse = await fetch( + `${apiBaseUrl}/providers/${encodeURIComponent(providerId)}`, + { headers, cache: "no-store" }, + ); + if (accountResponse.status === 401 || accountResponse.status === 403) + return { status: "access_denied" }; + if (!accountResponse.ok) return { status: "error" }; + const account = accountSchema.safeParse(await accountResponse.json()); + if ( + !account.success || + account.data.data.id !== providerId || + isKnownProviderType(account.data.data.attributes.provider) + ) + return { status: "error" }; + const schemas = await getProviderSchemas( + account.data.data.attributes.provider, + ); + if (schemas.status === "access_denied") return { status: "access_denied" }; + if ( + schemas.status !== "success" || + !Object.hasOwn(schemas.secretTypes, secretType) + ) + return { status: "schema_unavailable" }; + const schema = parseRegistryCredentialSchema( + schemas.secretTypes[secretType], + ); + if (!schema) return { status: "schema_unavailable" }; + const validated = validateCredentialValues(schema, secret); + if (!validated.valid) + return { status: "invalid", errors: validated.errors }; + + // Read the relationship again on every save so retries update a secret that + // was already created, including after a lost response. + const secretId = account.data.data.relationships.secret.data?.id; + const response = await fetch( + `${apiBaseUrl}/providers/secrets${secretId ? `/${encodeURIComponent(secretId)}` : ""}`, + { + method: secretId ? "PATCH" : "POST", + headers, + cache: "no-store", + body: JSON.stringify({ + data: { + type: "provider-secrets", + ...(secretId + ? { id: secretId } + : { + relationships: { + provider: { data: { id: providerId, type: "providers" } }, + }, + }), + attributes: { secret_type: secretType, secret: validated.secret }, + }, + }), + }, + ); + if (response.status === 401 || response.status === 403) + return { status: "access_denied" }; + // API validation details may echo credential values. Keep them out of both + // client errors and application logs. + if (!response.ok) return { status: "error" }; + const saved = z + .object({ data: z.object({ id: resourceId }) }) + .safeParse(await response.json()); + if (!saved.success) return { status: "error" }; + revalidatePath("/providers"); + return { status: "saved", secretId: saved.data.data.id }; + } catch { + return { status: "error" }; + } +} diff --git a/ui/actions/providers/index.ts b/ui/actions/providers/index.ts index 5532383f5f..d3580b7346 100644 --- a/ui/actions/providers/index.ts +++ b/ui/actions/providers/index.ts @@ -1 +1,2 @@ +export * from "./provider-schemas"; export * from "./providers"; diff --git a/ui/actions/providers/provider-schemas.adapter.test.ts b/ui/actions/providers/provider-schemas.adapter.test.ts new file mode 100644 index 0000000000..32c5e95fce --- /dev/null +++ b/ui/actions/providers/provider-schemas.adapter.test.ts @@ -0,0 +1,83 @@ +import { describe, expect, it } from "vitest"; + +import { + adaptProviderSchemas, + normalizeProviderType, +} from "./provider-schemas.adapter"; + +describe("provider schemas adapter", () => { + it("adapts a matching provider schema resource without interpreting schema keywords", () => { + // Given + const payload = { + data: { + type: "provider-schemas", + id: "acme", + attributes: { + secret_types: { + credentials: { + type: "object", + properties: { access_key: { type: "string" } }, + }, + }, + }, + }, + }; + + // When + const result = adaptProviderSchemas(payload, "acme"); + + // Then + expect(result).toEqual({ + status: "success", + providerType: "acme", + secretTypes: payload.data.attributes.secret_types, + }); + }); + + it.each([ + ["null", null], + ["string scalar", "secret"], + ["number scalar", 1], + ["boolean scalar", true], + ])("rejects %s secret_types values", (_description, secretType) => { + // Given + const payload = { + data: { + type: "provider-schemas", + id: "acme", + attributes: { secret_types: { credentials: secretType } }, + }, + }; + + // When + const result = adaptProviderSchemas(payload, "acme"); + + // Then + expect(result).toBeNull(); + }); + + it("rejects malformed or contradictory documents without reading schema keywords", () => { + // Given + const document = { + data: { + type: "provider-schemas", + id: "aws", + attributes: { secret_types: {} }, + }, + }; + + // When + const results = [ + { ...document, errors: [] }, + { data: { ...document.data, id: "aws " } }, + { data: { ...document.data, type: "providers" } }, + { data: { ...document.data, attributes: { secret_types: { key: [] } } } }, + ].map((payload) => adaptProviderSchemas(payload, "aws")); + + // Then + expect(results).toEqual([null, null, null, null]); + expect(normalizeProviderType(" AWS ")).toBe("aws"); + expect(normalizeProviderType(" ")).toBeNull(); + expect(normalizeProviderType("a".repeat(51))).toBeNull(); + }); +}); diff --git a/ui/actions/providers/provider-schemas.adapter.ts b/ui/actions/providers/provider-schemas.adapter.ts new file mode 100644 index 0000000000..9187afcf8f --- /dev/null +++ b/ui/actions/providers/provider-schemas.adapter.ts @@ -0,0 +1,38 @@ +import { z } from "zod"; + +import { + PROVIDER_SCHEMA_STATUS, + type ProviderSchemasSuccessResult, +} from "@/types/provider-schema"; + +const providerTypeSchema = z.string().trim().toLowerCase().min(1).max(50); +const providerSchemasDocumentSchema = z.strictObject({ + data: z.strictObject({ + type: z.literal("provider-schemas"), + id: z.string().min(1).max(50), + attributes: z.strictObject({ + secret_types: z.record(z.string(), z.record(z.string(), z.unknown())), + }), + }), +}); + +export function normalizeProviderType(value: unknown): string | null { + const parsed = providerTypeSchema.safeParse(value); + return parsed.success ? parsed.data : null; +} + +export function adaptProviderSchemas( + payload: unknown, + normalizedProviderType: string, +): ProviderSchemasSuccessResult | null { + const parsed = providerSchemasDocumentSchema.safeParse(payload); + if (!parsed.success || parsed.data.data.id !== normalizedProviderType) { + return null; + } + + return { + status: PROVIDER_SCHEMA_STATUS.SUCCESS, + providerType: parsed.data.data.id, + secretTypes: parsed.data.data.attributes.secret_types, + }; +} diff --git a/ui/actions/providers/provider-schemas.test.ts b/ui/actions/providers/provider-schemas.test.ts new file mode 100644 index 0000000000..0f6ead52f6 --- /dev/null +++ b/ui/actions/providers/provider-schemas.test.ts @@ -0,0 +1,138 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { authMock, fetchMock } = vi.hoisted(() => ({ + authMock: vi.fn(), + fetchMock: vi.fn(), +})); + +vi.mock("@/auth.config", () => ({ auth: authMock })); +vi.mock("@/lib", () => ({ apiBaseUrl: "https://api.test/api/v1" })); + +import { getProviderSchemas } from "./provider-schemas"; + +const schemaResponse = (providerType = "acme") => + new Response( + JSON.stringify({ + data: { + type: "provider-schemas", + id: providerType, + attributes: { secret_types: {} }, + }, + }), + { status: 200 }, + ); + +describe("getProviderSchemas", () => { + beforeEach(() => { + vi.clearAllMocks(); + vi.stubGlobal("fetch", fetchMock); + authMock.mockResolvedValue({ accessToken: "access-token" }); + fetchMock.mockResolvedValue(schemaResponse()); + }); + + it("requests the normalized provider schema with authenticated JSON:API headers", async () => { + // When + const result = await getProviderSchemas(" ACME "); + + // Then + expect(result).toEqual({ + status: "success", + providerType: "acme", + secretTypes: {}, + }); + expect(fetchMock).toHaveBeenCalledWith( + "https://api.test/api/v1/provider-schemas/acme", + { + cache: "no-store", + headers: { + Accept: "application/vnd.api+json", + Authorization: "Bearer access-token", + }, + }, + ); + }); + + it("does not fetch invalid input and encodes a normalized path segment", async () => { + // Given + fetchMock.mockResolvedValueOnce(schemaResponse("acme/team")); + + // When + const invalid = await Promise.all([ + getProviderSchemas(" "), + getProviderSchemas("a".repeat(51)), + ]); + const encoded = await getProviderSchemas(" ACME/TEAM "); + + // Then + expect(invalid).toEqual([{ status: "error" }, { status: "error" }]); + expect(encoded).toMatchObject({ + status: "success", + providerType: "acme/team", + }); + expect(fetchMock).toHaveBeenCalledOnce(); + expect(fetchMock).toHaveBeenCalledWith( + "https://api.test/api/v1/provider-schemas/acme%2Fteam", + expect.any(Object), + ); + }); + + it("denies an unauthenticated request without fetching", async () => { + // Given + authMock.mockResolvedValue({}); + + // When + const result = await getProviderSchemas("acme"); + + // Then + expect(result).toEqual({ status: "access_denied" }); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + it.each([ + [401, { status: "access_denied" }], + [403, { status: "access_denied" }], + [404, { status: "not_found" }], + [409, { status: "unavailable" }], + [500, { status: "error" }], + ])("maps HTTP %i to a safe result", async (status, expected) => { + // Given + fetchMock.mockResolvedValueOnce( + new Response(JSON.stringify({ errors: [{ detail: "private detail" }] }), { + status, + }), + ); + + // When + const result = await getProviderSchemas("acme"); + + // Then + expect(result).toEqual(expected); + expect(JSON.stringify(result)).not.toContain("private detail"); + }); + + it("returns a generic safe error when fetch rejects", async () => { + // Given + const rejection = new Error("connection detail must not leak"); + fetchMock.mockRejectedValueOnce(rejection); + + // When + const result = await getProviderSchemas("acme"); + + // Then + expect(result).toEqual({ status: "error" }); + expect(JSON.stringify(result)).not.toContain(rejection.message); + }); + + it("distinguishes a malformed success document from a transport failure", async () => { + // Given + fetchMock.mockResolvedValueOnce( + new Response(JSON.stringify({ errors: [] })), + ); + + // When + const result = await getProviderSchemas("acme"); + + // Then + expect(result).toEqual({ status: "malformed" }); + }); +}); diff --git a/ui/actions/providers/provider-schemas.ts b/ui/actions/providers/provider-schemas.ts new file mode 100644 index 0000000000..afdf0868d2 --- /dev/null +++ b/ui/actions/providers/provider-schemas.ts @@ -0,0 +1,61 @@ +"use server"; + +import { auth } from "@/auth.config"; +import { apiBaseUrl } from "@/lib"; +import { + PROVIDER_SCHEMA_STATUS, + type ProviderSchemasResult, +} from "@/types/provider-schema"; + +import { + adaptProviderSchemas, + normalizeProviderType, +} from "./provider-schemas.adapter"; + +export async function getProviderSchemas( + providerType: unknown, +): Promise { + const normalizedProviderType = normalizeProviderType(providerType); + if (!normalizedProviderType) return { status: PROVIDER_SCHEMA_STATUS.ERROR }; + + let accessToken: string | undefined; + try { + accessToken = (await auth())?.accessToken?.trim(); + } catch { + return { status: PROVIDER_SCHEMA_STATUS.ERROR }; + } + if (!accessToken) return { status: PROVIDER_SCHEMA_STATUS.ACCESS_DENIED }; + + let response: Response; + try { + response = await fetch( + `${apiBaseUrl}/provider-schemas/${encodeURIComponent(normalizedProviderType)}`, + { + cache: "no-store", + headers: { + Accept: "application/vnd.api+json", + Authorization: `Bearer ${accessToken}`, + }, + }, + ); + } catch { + return { status: PROVIDER_SCHEMA_STATUS.ERROR }; + } + + if (response.status === 401 || response.status === 403) { + return { status: PROVIDER_SCHEMA_STATUS.ACCESS_DENIED }; + } + if (response.status === 404) { + return { status: PROVIDER_SCHEMA_STATUS.NOT_FOUND }; + } + if (response.status === 409) { + return { status: PROVIDER_SCHEMA_STATUS.UNAVAILABLE }; + } + if (!response.ok) return { status: PROVIDER_SCHEMA_STATUS.ERROR }; + + const schema = adaptProviderSchemas( + await response.json().catch(() => undefined), + normalizedProviderType, + ); + return schema ?? { status: PROVIDER_SCHEMA_STATUS.MALFORMED }; +} diff --git a/ui/actions/providers/registry-provider.test.ts b/ui/actions/providers/registry-provider.test.ts new file mode 100644 index 0000000000..188cf43357 --- /dev/null +++ b/ui/actions/providers/registry-provider.test.ts @@ -0,0 +1,113 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { + getInstalledRegistryProviderOptions, + addProvider, + getProviders, + updateProvider, +} = vi.hoisted(() => ({ + getInstalledRegistryProviderOptions: vi.fn(), + addProvider: vi.fn(), + getProviders: vi.fn(), + updateProvider: vi.fn(), +})); +vi.mock("@/actions/registry/registry", () => ({ + getInstalledRegistryProviderOptions, +})); +vi.mock("./providers", () => ({ addProvider, getProviders, updateProvider })); + +import { addRegistryProvider } from "./registry-provider"; + +const formData = (alias = "Test") => { + const form = new FormData(); + form.set("providerType", "acme"); + form.set("providerUid", "account"); + form.set("providerAlias", alias); + return form; +}; +describe("Registry provider account creation", () => { + beforeEach(() => { + vi.clearAllMocks(); + getInstalledRegistryProviderOptions.mockResolvedValue({ + status: "ready", + options: [{ type: "acme", label: "Acme" }], + }); + getProviders.mockResolvedValue({ data: [] }); + }); + it("refuses removed artifacts and revoked permission before creating an account", async () => { + getInstalledRegistryProviderOptions + .mockResolvedValueOnce({ status: "access_denied" }) + .mockResolvedValueOnce({ status: "ready", options: [] }); + expect((await addRegistryProvider(formData()))?.errors).toBeDefined(); + expect((await addRegistryProvider(formData()))?.errors).toBeDefined(); + expect(addProvider).not.toHaveBeenCalled(); + }); + it("reuses a previously created account after a failed credential attempt or lost response", async () => { + const existing = { + id: "existing", + attributes: { provider: "acme", uid: "account", alias: "Test" }, + }; + getProviders.mockResolvedValue({ data: [existing] }); + expect(await addRegistryProvider(formData())).toEqual({ data: existing }); + expect(addProvider).not.toHaveBeenCalled(); + expect(updateProvider).not.toHaveBeenCalled(); + }); + it.each(["Test", "", " Edited "])( + "saves alias %j before resuming credentials for an existing account", + async (alias) => { + // Given + const existing = { + id: "existing", + attributes: { provider: "acme", uid: "account", alias: "Original" }, + }; + const updated = { + ...existing, + attributes: { ...existing.attributes, alias: alias.trim() }, + }; + getProviders.mockResolvedValue({ data: [existing] }); + updateProvider.mockResolvedValue({ data: updated }); + + // When + const result = await addRegistryProvider(formData(alias)); + + // Then + expect(result).toEqual({ data: updated }); + expect(Object.fromEntries(updateProvider.mock.calls[0][0])).toEqual({ + providerId: "existing", + providerAlias: alias.trim(), + }); + expect(addProvider).not.toHaveBeenCalled(); + }, + ); + it("keeps alias update failures visible instead of resuming with stale details", async () => { + // Given + const failure = { + errors: [ + { + detail: "Alias is invalid", + source: { pointer: "/data/attributes/alias" }, + }, + ], + }; + getProviders.mockResolvedValue({ + data: [ + { + id: "existing", + attributes: { provider: "acme", uid: "account", alias: "Original" }, + }, + ], + }); + updateProvider.mockResolvedValue(failure); + + // When / Then + await expect(addRegistryProvider(formData())).resolves.toEqual(failure); + expect(addProvider).not.toHaveBeenCalled(); + }); + it("creates a validated installed provider account", async () => { + addProvider.mockResolvedValue({ data: { id: "new" } }); + expect(await addRegistryProvider(formData())).toEqual({ + data: { id: "new" }, + }); + expect(addProvider).toHaveBeenCalledOnce(); + }); +}); diff --git a/ui/actions/providers/registry-provider.ts b/ui/actions/providers/registry-provider.ts new file mode 100644 index 0000000000..68fa43ce40 --- /dev/null +++ b/ui/actions/providers/registry-provider.ts @@ -0,0 +1,57 @@ +"use server"; + +import { getInstalledRegistryProviderOptions } from "@/actions/registry/registry"; +import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; +import { createAddProviderFormSchema } from "@/types/formSchemas"; +import { isKnownProviderType } from "@/types/providers"; + +import { addProvider, getProviders, updateProvider } from "./providers"; + +export async function addRegistryProvider(formData: FormData) { + const unavailable = { + errors: [ + { + detail: + "This Registry provider is no longer available. Check your permissions and installed artifacts, then try again.", + source: { pointer: "/data/attributes/provider" }, + }, + ], + }; + try { + const discovery = await getInstalledRegistryProviderOptions(); + if (discovery.status !== "ready") return unavailable; + const values = createAddProviderFormSchema( + discovery.options.map((option) => option.type), + ).safeParse(Object.fromEntries(formData)); + if (!values.success || isKnownProviderType(values.data.providerType)) + return unavailable; + const { providerType, providerUid } = values.data; + const existing = await getProviders({ + filters: { "filter[provider]": providerType, "filter[uid]": providerUid }, + pageSize: 100, + }); + // A previous request may have created the account before its response was + // lost. Reuse that identity when returning to the credential step. + if (!existing?.data) return unavailable; + const account = existing.data.find( + (provider) => + provider.attributes.provider === providerType && + provider.attributes.uid === providerUid, + ); + if (account) { + const alias = values.data.providerAlias.trim(); + if ((account.attributes.alias ?? "") === alias) return { data: account }; + const update = new FormData(); + update.set(ProviderCredentialFields.PROVIDER_ID, account.id); + update.set(ProviderCredentialFields.PROVIDER_ALIAS, alias); + return await updateProvider(update); + } + const validated = new FormData(); + Object.entries(values.data).forEach(([key, value]) => { + if (value !== undefined) validated.set(key, value); + }); + return await addProvider(validated); + } catch { + return unavailable; + } +} diff --git a/ui/actions/registry/registry.adapter.test.ts b/ui/actions/registry/registry.adapter.test.ts new file mode 100644 index 0000000000..dc35be5060 --- /dev/null +++ b/ui/actions/registry/registry.adapter.test.ts @@ -0,0 +1,696 @@ +import { describe, expect, it } from "vitest"; + +import { + REGISTRY_ENDPOINT, + REGISTRY_FAILURE, + REGISTRY_SUBMISSION, +} from "@/types/registry"; + +import { + adaptRegistryCredentialStatus, + adaptRegistryTenantArtifacts, + classifyRegistryFailure, + collectCompleteRegistryCatalog, + parseRegistryArtifactSubmission, +} from "./registry.adapter"; + +const credentialPayload = { + data: { + attributes: { + configured: true, + is_valid: true, + scopes: ["catalog:read"], + last_validated_at: "2026-03-20T12:00:00Z", + validation_status: "valid", + validation_pending: false, + key: "registry-secret-value", + masked_key: "reg_***", + pending_key: "queued-secret", + arbitrary_backend_detail: "do not expose", + }, + }, +}; + +const activeCredential = adaptRegistryCredentialStatus(credentialPayload); +const jsonError = (status: number, code: string) => + new Response( + JSON.stringify({ errors: [{ code, detail: "private detail" }] }), + { + status, + }, + ); + +describe("Registry adapter", () => { + it("reads the resolved installed version separately from the requested spec", () => { + // Given / When + const artifacts = adaptRegistryTenantArtifacts({ + data: [ + { + type: "registry-artifacts", + id: "template", + attributes: { + version_spec: "latest", + resolved_version: " 1.0.0 ", + }, + }, + ], + }); + // Then + expect(artifacts).toEqual([ + expect.objectContaining({ + normalizedName: "template", + versionSpec: "latest", + resolvedVersion: "1.0.0", + }), + ]); + }); + + it.each([undefined, null, "", " "])( + "accepts an unknown resolved version %j", + (resolvedVersion) => { + // Given / When + const artifacts = adaptRegistryTenantArtifacts({ + data: [ + { + type: "registry-artifacts", + id: "template", + attributes: { + version_spec: "latest", + resolved_version: resolvedVersion, + }, + }, + ], + }); + // Then + expect(artifacts).toMatchObject([{ resolvedVersion: undefined }]); + }, + ); + + it("maps only documented non-secret credential status fields", () => { + // Given + const malformedPayload = { data: { attributes: { configured: true } } }; + + // When + const status = adaptRegistryCredentialStatus(credentialPayload); + + // Then + expect(status).toEqual({ + configured: true, + isValid: true, + scopes: ["catalog:read"], + lastValidatedAt: "2026-03-20T12:00:00Z", + validationStatus: "valid", + validationPending: false, + }); + expect(adaptRegistryCredentialStatus(malformedPayload)).toBeNull(); + }); + + it("normalizes an absent credential status with nullable validation fields", () => { + // Given + const absentCredentialPayload = { + data: { + attributes: { + configured: false, + is_valid: false, + scopes: [], + last_validated_at: null, + validation_status: null, + validation_pending: false, + }, + }, + }; + + // When + const status = adaptRegistryCredentialStatus(absentCredentialPayload); + + // Then + expect(status).toEqual({ + configured: false, + isValid: false, + scopes: [], + lastValidatedAt: undefined, + validationStatus: undefined, + validationPending: false, + }); + }); + + it("accepts only a matching artifact 202 task and fixed Content-Location path", async () => { + // Given + const response = new Response( + JSON.stringify({ data: { type: "tasks", id: "task-123" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/task-123" }, + }, + ); + + // When + const result = await parseRegistryArtifactSubmission(response); + + // Then + expect(result).toEqual({ + status: REGISTRY_SUBMISSION.PENDING, + taskId: "task-123", + }); + }); + + it("rejects a non-202 response or a mismatched task location", async () => { + // Given + const task = JSON.stringify({ data: { type: "tasks", id: "task-123" } }); + const wrongStatus = new Response(task, { status: 201 }); + const wrongLocation = new Response(task, { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/other" }, + }); + + // When + const results = await Promise.all([ + parseRegistryArtifactSubmission(wrongStatus), + parseRegistryArtifactSubmission(wrongLocation), + ]); + + // Then + expect(results).toEqual([ + { status: REGISTRY_SUBMISSION.ERROR }, + { status: REGISTRY_SUBMISSION.ERROR }, + ]); + }); + + it("classifies every Registry 401 or 403 as access denied first", async () => { + // Given + const responses = [ + [401, REGISTRY_ENDPOINT.CREDENTIAL], + [403, REGISTRY_ENDPOINT.MUTATION], + [403, REGISTRY_ENDPOINT.PROVIDERS], + ] as const; + + // When + const results = await Promise.all( + responses.map(([status, endpoint]) => + classifyRegistryFailure( + jsonError(status, "registry_key_rejected"), + endpoint, + activeCredential, + ), + ), + ); + + // Then + expect(results).toEqual([ + { status: REGISTRY_FAILURE.ACCESS_DENIED }, + { status: REGISTRY_FAILURE.ACCESS_DENIED }, + { status: REGISTRY_FAILURE.ACCESS_DENIED }, + ]); + }); + + it("maps only a 409 with an authoritative no-active credential to onboarding", async () => { + // Given + const noCredential = adaptRegistryCredentialStatus({ + data: { + attributes: { + configured: false, + is_valid: false, + scopes: [], + validation_pending: false, + }, + }, + }); + + // When + const results = await Promise.all( + [noCredential, null].map((credential) => + classifyRegistryFailure( + new Response(null, { status: 409 }), + REGISTRY_ENDPOINT.AVAILABLE_ARTIFACTS, + credential, + ), + ), + ); + + // Then + expect(results).toEqual([ + { status: REGISTRY_FAILURE.ONBOARDING }, + { status: REGISTRY_FAILURE.ERROR }, + ]); + }); + + it("maps only exact documented 502 and 503 status-code pairs", async () => { + // Given + const rejected = jsonError(502, "registry_key_rejected"); + const unavailable = jsonError(503, "registry_unavailable"); + + // When + const results = await Promise.all([ + classifyRegistryFailure( + rejected, + REGISTRY_ENDPOINT.PROVIDERS, + activeCredential, + ), + classifyRegistryFailure( + unavailable, + REGISTRY_ENDPOINT.AVAILABLE_ARTIFACTS, + activeCredential, + ), + ]); + + // Then + expect(results).toEqual([ + { status: REGISTRY_FAILURE.RECONNECT }, + { status: REGISTRY_FAILURE.UNAVAILABLE }, + ]); + }); + + it("keeps wrong, malformed, and unrelated failures generic", async () => { + // Given + const malformed = new Response("key=private", { status: 503 }); + + // When + const results = await Promise.all([ + classifyRegistryFailure( + jsonError(502, "other_error"), + REGISTRY_ENDPOINT.PROVIDERS, + activeCredential, + ), + classifyRegistryFailure( + jsonError(502, "registry_unavailable"), + REGISTRY_ENDPOINT.PROVIDERS, + activeCredential, + ), + classifyRegistryFailure( + malformed, + REGISTRY_ENDPOINT.PROVIDERS, + activeCredential, + ), + ]); + + // Then + expect(results).toEqual([ + { status: REGISTRY_FAILURE.ERROR }, + { status: REGISTRY_FAILURE.ERROR }, + { status: REGISTRY_FAILURE.ERROR }, + ]); + }); + + it("degrades a non-terminal empty first catalog page", async () => { + // Given + const document = (page: number) => ({ + data: [], + meta: { pagination: { page, pages: 2, count: 0 } }, + }); + + // When + const result = await collectCompleteRegistryCatalog(async (page) => + document(page), + ); + + // Then + expect(result).toEqual({ + status: "incomplete", + reason: "invalid_page", + collectedCount: 0, + }); + }); + + it("accepts a terminal empty first catalog page", async () => { + // Given + const document = { + data: [], + meta: { pagination: { page: 1, pages: 1, count: 0 } }, + }; + + // When + const result = await collectCompleteRegistryCatalog(async () => document); + + // Then + expect(result).toEqual({ status: "complete", artifacts: [] }); + }); + + it("maps the flat owner attributes tolerantly", async () => { + // Given + const document = { + data: [ + { + type: "registry-artifacts", + id: "core", + attributes: { + owner_name: "Prowler", + owner_slug: "prowler", + owner_type: "organization", + owner_logo_url: "https://cdn.example/prowler.png", + }, + }, + { + type: "registry-artifacts", + id: "plain-owner", + attributes: { + owner_name: "Ada", + owner_slug: "ada", + owner_type: "user", + owner_logo_url: null, + }, + }, + { + type: "registry-artifacts", + id: "ownerless", + attributes: { owner_name: " ", owner_logo_url: " " }, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 3 } }, + }; + + // When + const result = await collectCompleteRegistryCatalog(async () => document); + + // Then + expect(result).toMatchObject({ + status: "complete", + artifacts: [ + { + normalizedName: "core", + owners: [ + { + type: "organization", + name: "Prowler", + logoUrl: "https://cdn.example/prowler.png", + }, + ], + }, + { + normalizedName: "ownerless", + owners: [], + }, + { + normalizedName: "plain-owner", + owners: [{ type: "user", name: "Ada", logoUrl: undefined }], + }, + ], + }); + }); + + it("defaults omitted built-in status and maps explicit built-ins", async () => { + // Given + const document = { + data: [ + { type: "registry-artifacts", id: "installable", attributes: {} }, + { + type: "registry-artifacts", + id: "built-in", + attributes: { is_builtin: true }, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 2 } }, + }; + + // When + const result = await collectCompleteRegistryCatalog(async () => document); + + // Then + expect(result).toMatchObject({ + status: "complete", + artifacts: [ + { normalizedName: "built-in", isBuiltin: true }, + { normalizedName: "installable", isBuiltin: false }, + ], + }); + }); + + it("rejects malformed built-in values and preserves built-in duplicates", async () => { + // Given + const document = (data: unknown[]) => ({ + data, + meta: { pagination: { page: 1, pages: 1, count: data.length } }, + }); + const resource = (id: string, isBuiltin: unknown) => ({ + type: "registry-artifacts", + id, + attributes: { is_builtin: isBuiltin }, + }); + + // When + const explicitFalse = await collectCompleteRegistryCatalog(async () => + document([resource("installable", false)]), + ); + const malformed = await Promise.all( + [null, "true", 1].map((isBuiltin) => + collectCompleteRegistryCatalog(async () => + document([resource("malformed", isBuiltin)]), + ), + ), + ); + const duplicate = await collectCompleteRegistryCatalog(async (page) => ({ + data: [resource("built-in", page === 2)], + meta: { pagination: { page, pages: 2, count: 2 } }, + })); + + // Then + expect(explicitFalse).toMatchObject({ + status: "complete", + artifacts: [{ normalizedName: "installable", isBuiltin: false }], + }); + expect(malformed).toEqual([ + { status: "incomplete", reason: "invalid_resource", collectedCount: 1 }, + { status: "incomplete", reason: "invalid_resource", collectedCount: 1 }, + { status: "incomplete", reason: "invalid_resource", collectedCount: 1 }, + ]); + expect(duplicate).toMatchObject({ + status: "complete", + artifacts: [{ normalizedName: "built-in", isBuiltin: true }], + }); + }); + + it("preserves artifact counts, including zero, without inventing missing counts", async () => { + // Given + const resources = [ + { id: "aws", attributes: { check_count: 645, compliance_count: 45 } }, + { id: "openai", attributes: { check_count: 2, compliance_count: 0 } }, + { id: "missing", attributes: {} }, + { + id: "unknown", + attributes: { check_count: null, compliance_count: null }, + }, + { id: "aws", attributes: { check_count: 645 } }, + ].map((resource) => ({ + type: "registry-available-artifacts", + ...resource, + })); + + // When + const result = await collectCompleteRegistryCatalog(async () => ({ + data: resources, + meta: { pagination: { page: 1, pages: 1, count: resources.length } }, + })); + + // Then + expect(result).toMatchObject({ + status: "complete", + artifacts: [ + { normalizedName: "aws", checkCount: 645, complianceCount: 45 }, + { + normalizedName: "missing", + checkCount: undefined, + complianceCount: undefined, + }, + { normalizedName: "openai", checkCount: 2, complianceCount: 0 }, + { + normalizedName: "unknown", + checkCount: undefined, + complianceCount: undefined, + }, + ], + }); + }); + + it("preserves the declared provider when merging complementary catalog entries", async () => { + // Given + const fetchPage = async (page: number) => ({ + data: [ + { + type: "registry-artifacts", + id: "external-package", + attributes: + page === 1 + ? { providers: ["aaa"], has_checks: true } + : { providers: ["zzz"], has_provider: true }, + }, + ], + meta: { pagination: { page, pages: 2, count: 2 } }, + }); + + // When + const result = await collectCompleteRegistryCatalog(fetchPage); + + // Then + expect(result).toMatchObject({ + status: "complete", + artifacts: [ + { hasProvider: true, providerSlug: "zzz", providers: ["aaa", "zzz"] }, + ], + }); + }); + + it("rejects duplicate catalog entries with conflicting declared providers", async () => { + // Given + const fetchPage = async (page: number) => ({ + data: [ + { + type: "registry-artifacts", + id: "external-package", + attributes: { + has_provider: true, + providers: [page === 1 ? "aaa" : "zzz"], + }, + }, + ], + meta: { pagination: { page, pages: 2, count: 2 } }, + }); + + // When / Then + await expect( + collectCompleteRegistryCatalog(fetchPage), + ).resolves.toMatchObject({ + status: "incomplete", + reason: "conflicting_duplicate", + }); + }); + + it("traverses, merges, and degrades unsafe catalog data", async () => { + // Given + + const resource = ( + id: string, + attributes: Record = {}, + ) => ({ type: "registry-artifacts", id, attributes }); + + const document = ( + page: number, + pages: number, + count: number, + data: unknown[], + ) => ({ data, meta: { pagination: { page, pages, count } } }); + const requests: Array<[number, string | null, string | null]> = []; + + // When + + const complete = await collectCompleteRegistryCatalog( + async (page, query) => { + requests.push([ + page, + query.get("page[number]"), + query.get("page[size]"), + ]); + return page === 1 + ? document(1, 2, 3, [ + resource("core", { + name: "Core", + providers: ["AWS"], + is_verified: true, + version_count: 1, + total_downloads: 2, + owner_name: "Prowler", + owner_type: "organization", + }), + resource("zeta"), + ]) + : document(2, 2, 3, [ + resource("core", { + description: "Registry core", + latest_version: "2.0.0", + providers: ["gcp"], + is_official: true, + has_checks: true, + version_count: 3, + total_downloads: 8, + }), + ]); + }, + ); + + const limits = await Promise.all( + [999, 1000, 1001].map(async (pages) => { + let requests = 0; + const result = await collectCompleteRegistryCatalog(async (page) => { + requests += 1; + return document(page, pages, pages, [resource(`item-${page}`)]); + }); + return [pages, requests, result] as const; + }), + ); + + const failures = await Promise.all([ + collectCompleteRegistryCatalog(async () => ({ data: {}, meta: {} })), + collectCompleteRegistryCatalog(async () => + document(1, 1, 2, [resource("one")]), + ), + collectCompleteRegistryCatalog(async (page) => + document(page === 1 ? 1 : 1, 2, 2, [resource(`item-${page}`)]), + ), + collectCompleteRegistryCatalog(async (page) => + document(page, page === 1 ? 2 : 3, 2, [resource(`item-${page}`)]), + ), + collectCompleteRegistryCatalog(async () => + document(1, 1, 1, [resource("")]), + ), + collectCompleteRegistryCatalog(async (page) => + document(page, 2, 2, [ + resource("duplicate", { name: page === 1 ? "One" : "Two" }), + ]), + ), + collectCompleteRegistryCatalog(async (page) => { + if (page === 2) throw new Error("offline"); + return document(1, 2, 2, [resource("first")]); + }), + ]); + + // Then + expect(requests).toEqual([ + [1, "1", "100"], + [2, "2", "100"], + ]); + + expect(complete).toMatchObject({ + status: "complete", + artifacts: [ + { + normalizedName: "core", + name: "Core", + description: "Registry core", + latestVersion: "2.0.0", + providers: ["aws", "gcp"], + isVerified: true, + isOfficial: true, + hasChecks: true, + versionCount: 3, + totalDownloads: 8, + owners: [{ type: "organization", name: "Prowler" }], + }, + { normalizedName: "zeta" }, + ], + }); + expect(limits.map(([pages, requests]) => [pages, requests])).toEqual([ + [999, 999], + [1000, 1000], + [1001, 1], + ]); + expect(limits[2]?.[2]).toEqual({ + status: "incomplete", + reason: "guard_exhausted", + collectedCount: 1, + }); + expect( + failures.map((result) => + result.status === "incomplete" ? result.reason : undefined, + ), + ).toEqual([ + "invalid_page", + "count_mismatch", + "invalid_page", + "invalid_page", + "invalid_resource", + "conflicting_duplicate", + "page_failed", + ]); + failures.forEach((result) => + expect(result).not.toHaveProperty("artifacts"), + ); + }); +}); diff --git a/ui/actions/registry/registry.adapter.ts b/ui/actions/registry/registry.adapter.ts new file mode 100644 index 0000000000..46bd08d8e0 --- /dev/null +++ b/ui/actions/registry/registry.adapter.ts @@ -0,0 +1,441 @@ +import { z } from "zod"; + +import { isActiveRegistryCredential } from "@/lib/registry/credential-task"; +import { + REGISTRY_CATALOG, + REGISTRY_CATALOG_INCOMPLETE_REASON, + REGISTRY_ENDPOINT, + REGISTRY_FAILURE, + REGISTRY_MUTATION, + REGISTRY_SUBMISSION, + type RegistryCatalogArtifact, + type RegistryCatalogResult, + type RegistryCredentialStatus, + type RegistryTaskSubmissionResult, + type RegistryEndpoint, + type RegistryFailureResult, + type RegistryMutationResult, + type RegistryTenantArtifact, +} from "@/types/registry"; + +const REGISTRY_TASK_PATH_PREFIX = "/api/v1/tasks/"; +const REGISTRY_ERROR_CODE = { + KEY_REJECTED: "registry_key_rejected", + UNAVAILABLE: "registry_unavailable", +} as const; +const REGISTRY_MUTATION_REFUSAL_COPY = { + no_installable_version: "No available version can be added.", + registry_artifact_not_found: "This artifact is no longer available.", + version_not_found: "This version is not available.", + version_not_processed: "This version is not ready to add yet.", + version_not_verified: "This version is not verified and cannot be added.", + version_yanked: "This version is no longer available.", +} as const; +const registryDiscoveryEndpoints = new Set([ + REGISTRY_ENDPOINT.PROVIDERS, + REGISTRY_ENDPOINT.AVAILABLE_ARTIFACTS, +]); + +const credentialStatusSchema = z.object({ + data: z.object({ + attributes: z.object({ + configured: z.boolean(), + is_valid: z.boolean(), + scopes: z.array(z.string()), + last_validated_at: z.string().nullish(), + validation_status: z.string().nullish(), + validation_pending: z.boolean(), + }), + }), +}); + +const taskSubmissionSchema = z.object({ + data: z.object({ + type: z.literal("tasks"), + id: z.string().min(1), + }), +}); + +const registryCollectionSchema = z.object({ data: z.array(z.unknown()) }); +const tenantArtifactsSchema = z.object({ + data: z.array( + z.object({ + type: z.string().trim().min(1), + id: z.string().trim().min(1), + attributes: z.object({ + version_spec: z.string().trim().min(1), + resolved_version: z.string().trim().nullish(), + inserted_at: z.string().optional(), + updated_at: z.string().optional(), + }), + }), + ), +}); + +const errorDocumentSchema = z.object({ + errors: z.array(z.object({ code: z.string().min(1) })).min(1), +}); + +export function adaptRegistryCredentialStatus( + payload: unknown, +): RegistryCredentialStatus | null { + const parsed = credentialStatusSchema.safeParse(payload); + if (!parsed.success) return null; + + const { attributes } = parsed.data.data; + return { + configured: attributes.configured, + isValid: attributes.is_valid, + scopes: attributes.scopes, + lastValidatedAt: attributes.last_validated_at ?? undefined, + validationStatus: attributes.validation_status ?? undefined, + validationPending: attributes.validation_pending, + }; +} + +export function adaptRegistryTenantArtifacts( + payload: unknown, +): RegistryTenantArtifact[] | null { + const parsed = tenantArtifactsSchema.safeParse(payload); + if (!parsed.success) return null; + + return parsed.data.data.map(({ attributes, id }) => ({ + normalizedName: id, + versionSpec: attributes.version_spec, + resolvedVersion: attributes.resolved_version || undefined, + insertedAt: attributes.inserted_at, + updatedAt: attributes.updated_at, + })); +} + +export function isRegistryCollection(payload: unknown) { + return registryCollectionSchema.safeParse(payload).success; +} + +export class RegistryCatalogPageError extends Error { + constructor(readonly failure: RegistryFailureResult) { + super("Registry catalog page request failed"); + } +} + +export const parseRegistryCredentialSubmission = ( + response: Response, +): Promise => + parseRegistryTaskSubmission(response); + +export const parseRegistryArtifactSubmission = ( + response: Response, +): Promise => + parseRegistryTaskSubmission(response); + +async function parseRegistryTaskSubmission( + response: Response, +): Promise { + if (response.status !== 202) return { status: REGISTRY_SUBMISSION.ERROR }; + + const parsed = taskSubmissionSchema.safeParse( + await response.json().catch(() => undefined), + ); + const taskId = parsed.success ? parsed.data.data.id : undefined; + const location = response.headers.get("Content-Location"); + if ( + !taskId || + location !== `${REGISTRY_TASK_PATH_PREFIX}${encodeURIComponent(taskId)}` + ) { + return { status: REGISTRY_SUBMISSION.ERROR }; + } + + return { status: REGISTRY_SUBMISSION.PENDING, taskId }; +} + +export async function classifyRegistryMutationRefusal( + response: Response, +): Promise | null> { + const code = await getRegistryErrorCode(response); + const message = code + ? REGISTRY_MUTATION_REFUSAL_COPY[ + code as keyof typeof REGISTRY_MUTATION_REFUSAL_COPY + ] + : undefined; + return message ? { status: REGISTRY_MUTATION.REFUSED, message } : null; +} + +export async function classifyRegistryFailure( + response: Response, + endpoint: RegistryEndpoint, + credentialStatus: RegistryCredentialStatus | null, +): Promise { + if (response.status === 401 || response.status === 403) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + } + + if (!isRegistryDiscoveryEndpoint(endpoint)) { + return { status: REGISTRY_FAILURE.ERROR }; + } + + if ( + response.status === 409 && + credentialStatus !== null && + !isActiveRegistryCredential(credentialStatus) + ) { + return { status: REGISTRY_FAILURE.ONBOARDING }; + } + + const code = await getRegistryErrorCode(response); + if (response.status === 502 && code === REGISTRY_ERROR_CODE.KEY_REJECTED) { + return { status: REGISTRY_FAILURE.RECONNECT }; + } + if (response.status === 503 && code === REGISTRY_ERROR_CODE.UNAVAILABLE) { + return { status: REGISTRY_FAILURE.UNAVAILABLE }; + } + + return { status: REGISTRY_FAILURE.ERROR }; +} + +function isRegistryDiscoveryEndpoint(endpoint: RegistryEndpoint) { + return registryDiscoveryEndpoints.has(endpoint); +} + +async function getRegistryErrorCode(response: Response) { + const parsed = errorDocumentSchema.safeParse( + await response + .clone() + .json() + .catch(() => undefined), + ); + return parsed.success ? parsed.data.errors[0]?.code : undefined; +} + +const REGISTRY_CATALOG_PAGE_SIZE = 100; +const REGISTRY_CATALOG_MAX_PAGES = 1000; +const safeInteger = z.number().int().nonnegative().safe(); +const catalogPageSchema = z.object({ + data: z.array(z.unknown()), + meta: z.object({ + pagination: z.object({ + page: safeInteger, + pages: safeInteger, + count: safeInteger, + }), + }), +}); +const catalogAttributesSchema = z.object({ + name: z.string().optional(), + description: z.string().optional(), + latest_version: z.string().optional(), + providers: z.array(z.string().trim().min(1)).optional(), + owner_name: z.string().optional(), + owner_type: z.string().optional(), + owner_logo_url: z.string().nullable().optional(), + is_verified: z.boolean().optional(), + is_official: z.boolean().optional(), + is_builtin: z.boolean().optional(), + is_meta: z.boolean().optional(), + has_provider: z.boolean().optional(), + has_checks: z.boolean().optional(), + has_compliance: z.boolean().optional(), + check_count: safeInteger.nullish(), + compliance_count: safeInteger.nullish(), + version_count: safeInteger.optional(), + total_downloads: safeInteger.optional(), +}); +const catalogResourceSchema = z.object({ + type: z.string().trim().min(1), + id: z.string().trim().min(1), + attributes: catalogAttributesSchema, +}); +type RegistryCatalogPageFetcher = ( + page: number, + searchParams: URLSearchParams, +) => Promise; + +export async function collectCompleteRegistryCatalog( + fetchPage: RegistryCatalogPageFetcher, +): Promise { + const resources: unknown[] = []; + let expectedPages: number | undefined; + let expectedCount: number | undefined; + for (let page = 1; ; page += 1) { + let payload: unknown; + try { + payload = await fetchPage( + page, + new URLSearchParams({ + "page[number]": String(page), + "page[size]": String(REGISTRY_CATALOG_PAGE_SIZE), + }), + ); + } catch (error) { + if (error instanceof RegistryCatalogPageError) throw error; + return incomplete("PAGE_FAILED", resources.length); + } + const parsed = catalogPageSchema.safeParse(payload); + if (!parsed.success) return incomplete("INVALID_PAGE", resources.length); + const { count, page: responsePage, pages } = parsed.data.meta.pagination; + if ( + responsePage !== page || + (expectedPages !== undefined && + (pages !== expectedPages || count !== expectedCount)) + ) + return incomplete("INVALID_PAGE", resources.length); + expectedPages ??= pages; + expectedCount ??= count; + if (page === 1 && pages > 1 && count === 0 && parsed.data.data.length === 0) + return incomplete("INVALID_PAGE", resources.length); + if (pages === 0) + return page === 1 && count === 0 && parsed.data.data.length === 0 + ? { status: REGISTRY_CATALOG.COMPLETE, artifacts: [] } + : incomplete("INVALID_PAGE", resources.length); + resources.push(...parsed.data.data); + if (pages > REGISTRY_CATALOG_MAX_PAGES) + return incomplete("GUARD_EXHAUSTED", resources.length); + if (page === pages) break; + if (page > pages) return incomplete("INVALID_PAGE", resources.length); + } + const merged = mergeCatalogResources(resources); + return merged.status === REGISTRY_CATALOG.INCOMPLETE || + resources.length === expectedCount + ? merged + : incomplete("COUNT_MISMATCH", resources.length); +} + +function mergeCatalogResources(resources: unknown[]): RegistryCatalogResult { + const artifacts = new Map(); + for (const resource of resources) { + const artifact = adaptCatalogArtifact(resource); + if (!artifact) return incomplete("INVALID_RESOURCE", resources.length); + const prior = artifacts.get(artifact.normalizedName); + const next = prior ? mergeArtifacts(prior, artifact) : artifact; + if (!next) return incomplete("CONFLICTING_DUPLICATE", resources.length); + artifacts.set(next.normalizedName, next); + } + return { + status: REGISTRY_CATALOG.COMPLETE, + artifacts: Array.from(artifacts.values()).sort((left, right) => + compare(left.normalizedName, right.normalizedName), + ), + }; +} + +function adaptCatalogArtifact( + resource: unknown, +): RegistryCatalogArtifact | null { + const parsed = catalogResourceSchema.safeParse(resource); + if (!parsed.success) return null; + const { attributes: a, id } = parsed.data; + return { + normalizedName: id, + name: text(a.name), + description: text(a.description), + latestVersion: text(a.latest_version), + providers: unique( + a.providers?.map((provider) => provider.toLowerCase()) ?? [], + ), + ...(a.has_provider === true && a.providers?.[0] + ? { providerSlug: a.providers[0].toLowerCase() } + : {}), + owners: flatOwner(a), + isVerified: a.is_verified ?? false, + isOfficial: a.is_official ?? false, + isBuiltin: a.is_builtin ?? false, + isMeta: a.is_meta ?? false, + hasProvider: a.has_provider ?? false, + hasChecks: a.has_checks ?? false, + hasCompliance: a.has_compliance ?? false, + checkCount: a.check_count ?? undefined, + complianceCount: a.compliance_count ?? undefined, + versionCount: a.version_count ?? 0, + totalDownloads: a.total_downloads ?? 0, + }; +} + +function mergeArtifacts( + left: RegistryCatalogArtifact, + right: RegistryCatalogArtifact, +): RegistryCatalogArtifact | null { + const [name, description, latestVersion, providerSlug] = [ + mergeText(left.name, right.name), + mergeText(left.description, right.description), + mergeText(left.latestVersion, right.latestVersion), + mergeText(left.providerSlug, right.providerSlug), + ]; + if ( + [name, description, latestVersion, providerSlug].some( + (value) => value === null, + ) + ) + return null; + return { + ...left, + name: name ?? undefined, + description: description ?? undefined, + latestVersion: latestVersion ?? undefined, + providerSlug: providerSlug ?? undefined, + providers: unique([...left.providers, ...right.providers]), + owners: uniqueOwners([...left.owners, ...right.owners]), + isVerified: left.isVerified || right.isVerified, + isOfficial: left.isOfficial || right.isOfficial, + isBuiltin: left.isBuiltin || right.isBuiltin, + isMeta: left.isMeta || right.isMeta, + hasProvider: left.hasProvider || right.hasProvider, + hasChecks: left.hasChecks || right.hasChecks, + hasCompliance: left.hasCompliance || right.hasCompliance, + checkCount: mergeCount(left.checkCount, right.checkCount), + complianceCount: mergeCount(left.complianceCount, right.complianceCount), + versionCount: Math.max(left.versionCount, right.versionCount), + totalDownloads: Math.max(left.totalDownloads, right.totalDownloads), + }; +} + +function incomplete( + reason: keyof typeof REGISTRY_CATALOG_INCOMPLETE_REASON, + collectedCount: number, +): RegistryCatalogResult { + return { + status: REGISTRY_CATALOG.INCOMPLETE, + reason: REGISTRY_CATALOG_INCOMPLETE_REASON[reason], + collectedCount, + }; +} +function text(value: string | undefined) { + return value?.trim() || undefined; +} +function mergeText(left: string | undefined, right: string | undefined) { + return left && right && left !== right ? null : (left ?? right); +} +function mergeCount(left: number | undefined, right: number | undefined) { + if (left === undefined) return right; + if (right === undefined) return left; + return Math.max(left, right); +} +function unique(values: string[]) { + return Array.from(new Set(values)).sort(compare); +} +function flatOwner( + a: z.infer, +): RegistryCatalogArtifact["owners"] { + const name = text(a.owner_name); + if (!name) return []; + return [ + { + name, + type: text(a.owner_type) ?? "", + logoUrl: text(a.owner_logo_url ?? undefined), + }, + ]; +} +function uniqueOwners(owners: RegistryCatalogArtifact["owners"]) { + return Array.from( + new Map( + owners.map((owner) => [`${owner.type}\u0000${owner.name}`, owner]), + ).values(), + ).sort((left, right) => + compare( + `${left.type}\u0000${left.name}`, + `${right.type}\u0000${right.name}`, + ), + ); +} +function compare(left: string, right: string) { + return left < right ? -1 : left > right ? 1 : 0; +} diff --git a/ui/actions/registry/registry.test.ts b/ui/actions/registry/registry.test.ts new file mode 100644 index 0000000000..f81ee78d23 --- /dev/null +++ b/ui/actions/registry/registry.test.ts @@ -0,0 +1,1138 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { + authMock, + evaluateAccessMock, + evaluateProviderAccessMock, + fetchMock, + pollTaskUntilSettledMock, +} = vi.hoisted(() => ({ + authMock: vi.fn(), + evaluateAccessMock: vi.fn(), + evaluateProviderAccessMock: vi.fn(), + fetchMock: vi.fn(), + pollTaskUntilSettledMock: vi.fn(), +})); + +vi.mock("@/auth.config", () => ({ auth: authMock })); +vi.mock("@/lib", () => ({ apiBaseUrl: "https://api.test/api/v1" })); +vi.mock("@/actions/task/poll", () => ({ + pollTaskUntilSettled: pollTaskUntilSettledMock, +})); +vi.mock("@/lib/registry/access.server", () => ({ + evaluateRegistryAccess: evaluateAccessMock, + evaluateRegistryProviderAccess: evaluateProviderAccessMock, +})); + +import { + addRegistryArtifact, + confirmRegistryArtifactAddition, + disconnectRegistryCredential, + getRegistryBootstrap, + getInstalledRegistryProviderOptions, + refreshRegistryCollections, + removeRegistryArtifact, + refreshRegistryCredential, + submitRegistryCredential, +} from "./registry"; + +const activeCredential = { + configured: true, + isValid: true, + scopes: ["catalog:read"], + validationPending: false, +}; +const noCredential = { + configured: false, + isValid: false, + scopes: [], + validationPending: false, +}; +const pendingCredential = { + configured: true, + isValid: false, + scopes: [], + validationPending: true, +}; + +const jsonResponse = (body: unknown, status = 200) => + new Response(JSON.stringify(body), { + status, + headers: { "Content-Type": "application/vnd.api+json" }, + }); +const credentialResponse = (credential = activeCredential) => + jsonResponse({ + data: { + attributes: { + configured: credential.configured, + is_valid: credential.isValid, + scopes: credential.scopes, + validation_pending: credential.validationPending, + }, + }, + }); +const tenantArtifactsResponse = () => + jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "prowler-aws", + attributes: { + version_spec: "latest", + inserted_at: "2026-03-20T12:00:00Z", + }, + }, + ], + }); +const catalogResponse = () => + jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "prowler-aws", + attributes: { name: "Prowler AWS", providers: ["aws"] }, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 1 } }, + }); + +beforeEach(() => { + vi.stubGlobal("fetch", fetchMock); + authMock.mockResolvedValue({ accessToken: "access-token" }); + evaluateAccessMock.mockResolvedValue({ status: "eligible" }); + evaluateProviderAccessMock.mockResolvedValue({ status: "eligible" }); + fetchMock.mockReset(); + pollTaskUntilSettledMock.mockReset(); +}); + +function mockRequestDeadlines() { + // Native AbortSignal.timeout uses real timers; drive it with the test clock. + vi.spyOn(AbortSignal, "timeout").mockImplementation((milliseconds) => { + const controller = new AbortController(); + setTimeout(() => controller.abort(), milliseconds); + return controller.signal; + }); +} + +describe("installed Registry provider discovery", () => { + function mockDiscovery({ + emptyMetadata = false, + failedEndpoint, + failureStatus = 500, + }: { + emptyMetadata?: boolean; + failedEndpoint?: string; + failureStatus?: number; + } = {}) { + fetchMock.mockImplementation((url: string) => { + const endpoint = new URL(url).pathname.split("/").pop(); + if (endpoint === failedEndpoint) return jsonResponse({}, failureStatus); + if (endpoint === "available-artifacts") + return jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "acme-package", + attributes: { + name: "Acme package", + providers: ["acme"], + has_provider: true, + }, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 1 } }, + }); + if (endpoint === "artifacts") + return jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "acme-package", + attributes: { version_spec: "latest" }, + }, + ], + }); + if (endpoint === "providers") + return jsonResponse({ + data: emptyMetadata + ? [] + : [ + { + id: "acme", + attributes: { + name: "Acme Cloud", + logo_url: "https://media.registry.test/acme.svg", + }, + }, + ], + }); + throw new Error(`Unexpected endpoint: ${endpoint}`); + }); + } + + it("joins catalog declarations, installed membership and provider metadata", async () => { + mockDiscovery(); + expect(await getInstalledRegistryProviderOptions()).toEqual({ + status: "ready", + options: [ + { + type: "acme", + label: "Acme Cloud", + logoUrl: "https://media.registry.test/acme.svg", + }, + ], + }); + }); + + it("allows installed-provider discovery without Registry management access", async () => { + // Given + mockDiscovery({ emptyMetadata: true }); + evaluateAccessMock.mockResolvedValue({ status: "ineligible" }); + // When / Then + expect(await getInstalledRegistryProviderOptions()).toEqual({ + status: "ready", + options: [{ type: "acme", label: "Acme package" }], + }); + expect(evaluateProviderAccessMock).toHaveBeenCalledWith("access-token"); + expect(evaluateAccessMock).not.toHaveBeenCalled(); + }); + + it.each(["ineligible", "unknown"])( + "denies installed-provider discovery when provider access is %s", + async (status) => { + // Given + evaluateProviderAccessMock.mockResolvedValue({ status }); + // When / Then + expect(await getInstalledRegistryProviderOptions()).toEqual({ + status: "access_denied", + }); + expect(fetchMock).not.toHaveBeenCalled(); + }, + ); + + it("uses the declared provider and artifact name when metadata is empty", async () => { + mockDiscovery({ emptyMetadata: true }); + expect(await getInstalledRegistryProviderOptions()).toEqual({ + status: "ready", + options: [{ type: "acme", label: "Acme package" }], + }); + }); + + it.each(["available-artifacts", "artifacts", "providers"])( + "returns an error when the %s read fails", + async (failedEndpoint) => { + mockDiscovery({ failedEndpoint }); + expect(await getInstalledRegistryProviderOptions()).toEqual({ + status: "error", + }); + }, + ); + + it.each(["available-artifacts", "artifacts", "providers"])( + "preserves access denial from the %s read", + async (failedEndpoint) => { + mockDiscovery({ failedEndpoint, failureStatus: 403 }); + expect(await getInstalledRegistryProviderOptions()).toEqual({ + status: "access_denied", + }); + }, + ); +}); + +describe("Registry guarded reads", () => { + it("recovers when a Registry read stalls", async () => { + // Given: the upstream responds only when its request is aborted. + vi.useFakeTimers(); + try { + mockRequestDeadlines(); + fetchMock.mockImplementation( + (_url, init?: RequestInit) => + new Promise((_resolve, reject) => { + init?.signal?.addEventListener("abort", () => + reject(init.signal?.reason), + ); + }), + ); + const settled = vi.fn(); + + // When + void refreshRegistryCredential().then(settled); + await vi.advanceTimersByTimeAsync(30_000); + + // Then + expect(settled).toHaveBeenCalledWith({ status: "error" }); + } finally { + vi.useRealTimers(); + } + }); + + it.each([ + [ + "credential submission", + () => submitRegistryCredential("registry-test-key"), + ], + ["credential disconnection", disconnectRegistryCredential], + [ + "artifact addition", + () => addRegistryArtifact({ normalizedName: "external-package" }), + ], + ["artifact removal", () => removeRegistryArtifact("external-package")], + ])("recovers when %s stalls", async (_name, action) => { + // Given: prerequisite reads succeed, but the mutation never responds. + vi.useFakeTimers(); + try { + mockRequestDeadlines(); + fetchMock.mockImplementation((url: string, init?: RequestInit) => { + if (init?.method === "POST" || init?.method === "DELETE") { + return new Promise((_resolve, reject) => { + init.signal?.addEventListener("abort", () => + reject(init.signal?.reason), + ); + }); + } + if (url.includes("available-artifacts")) { + return Promise.resolve( + jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "external-package", + attributes: { has_provider: true, is_builtin: false }, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 1 } }, + }), + ); + } + return Promise.resolve(credentialResponse(noCredential)); + }); + const settled = vi.fn(); + + // When + void action().then(settled); + await vi.advanceTimersByTimeAsync(30_000); + + // Then + expect(settled).toHaveBeenCalledWith({ status: "error" }); + } finally { + vi.useRealTimers(); + } + }); + + it("denies Registry management actions before any Registry endpoint call", async () => { + // Given + evaluateAccessMock.mockResolvedValue({ status: "ineligible" }); + const actions = [ + getRegistryBootstrap, + refreshRegistryCredential, + refreshRegistryCollections, + () => submitRegistryCredential("registry-test-key"), + disconnectRegistryCredential, + ]; + + // When + const results = await Promise.all(actions.map((action) => action())); + + // Then + expect(results).toEqual(actions.map(() => ({ status: "access_denied" }))); + expect(evaluateAccessMock).toHaveBeenCalledTimes(actions.length); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + it.each(["unknown", "ineligible"])( + "does not fetch Registry collections when access is %s", + async (status) => { + // Given + evaluateAccessMock.mockResolvedValue({ status }); + + // When + const results = await Promise.all([ + getRegistryBootstrap(), + refreshRegistryCredential(), + refreshRegistryCollections(), + ]); + + // Then + expect(results).toEqual([ + { status: "access_denied" }, + { status: "access_denied" }, + { status: status === "unknown" ? "error" : "access_denied" }, + ]); + expect(fetchMock).not.toHaveBeenCalled(); + }, + ); + + it("bootstraps in credential, tenant-artifact, then complete-catalog order", async () => { + // Given + fetchMock + .mockResolvedValueOnce(credentialResponse()) + .mockResolvedValueOnce(tenantArtifactsResponse()) + .mockResolvedValueOnce(catalogResponse()); + + // When + const result = await getRegistryBootstrap(); + + // Then + expect(result).toEqual({ + status: "ready", + state: { + status: "ready", + credential: activeCredential, + catalog: { + status: "complete", + artifacts: [ + expect.objectContaining({ normalizedName: "prowler-aws" }), + ], + }, + tenantArtifacts: [ + { + normalizedName: "prowler-aws", + versionSpec: "latest", + insertedAt: "2026-03-20T12:00:00Z", + }, + ], + }, + }); + expect(fetchMock.mock.calls.map(([url]) => url)).toEqual([ + "https://api.test/api/v1/registry/credential", + "https://api.test/api/v1/registry/artifacts", + "https://api.test/api/v1/registry/available-artifacts?page%5Bnumber%5D=1&page%5Bsize%5D=100", + ]); + fetchMock.mock.calls.forEach(([, options]) => { + expect(options).toMatchObject({ + cache: "no-store", + headers: { + Accept: "application/vnd.api+json", + Authorization: "Bearer access-token", + }, + }); + }); + }); + + it.each([ + [noCredential, "onboarding"], + [pendingCredential, "validation_pending"], + ] as const)( + "blocks catalog bootstrap as %s credential is authoritative", + async (credential, expectedStatus) => { + // Given + fetchMock + .mockResolvedValueOnce(credentialResponse(credential)) + .mockResolvedValueOnce(tenantArtifactsResponse()); + + // When + const result = await getRegistryBootstrap(); + + // Then + expect(result).toEqual({ + status: "ready", + state: { + status: expectedStatus, + credential, + tenantArtifacts: [ + { + normalizedName: "prowler-aws", + versionSpec: "latest", + insertedAt: "2026-03-20T12:00:00Z", + }, + ], + }, + }); + expect(fetchMock).toHaveBeenCalledTimes(2); + }, + ); + + it("returns only a non-secret status read after a fresh guard", async () => { + // Given + fetchMock.mockResolvedValueOnce(credentialResponse()); + + // When + const result = await refreshRegistryCredential(); + + // Then + expect(result).toEqual({ status: "status", credential: activeCredential }); + expect(fetchMock).toHaveBeenCalledWith( + "https://api.test/api/v1/registry/credential", + expect.objectContaining({ cache: "no-store" }), + ); + }); + + it("returns fresh complete collections", async () => { + // Given + fetchMock + .mockResolvedValueOnce(catalogResponse()) + .mockResolvedValueOnce(tenantArtifactsResponse()); + + // When + const result = await refreshRegistryCollections(); + + // Then + expect(result).toEqual({ + status: "complete", + catalog: { + status: "complete", + artifacts: [expect.objectContaining({ normalizedName: "prowler-aws" })], + }, + tenantArtifacts: [ + { + normalizedName: "prowler-aws", + versionSpec: "latest", + insertedAt: "2026-03-20T12:00:00Z", + }, + ], + }); + expect(evaluateAccessMock).toHaveBeenCalledWith("access-token"); + }); + + it("maps a discovery 409 to onboarding after an authoritative no-credential read", async () => { + // Given + fetchMock + .mockResolvedValueOnce(jsonResponse({ errors: [] }, 409)) + .mockResolvedValueOnce(credentialResponse(noCredential)); + + // When + const result = await refreshRegistryCollections(); + + // Then + expect(result).toEqual({ status: "onboarding" }); + expect(fetchMock).toHaveBeenCalledTimes(2); + }); + + it("maps documented read recovery without exposing retained or partial catalog data", async () => { + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ errors: [{ code: "registry_key_rejected" }] }, 502), + ); + + // When + const reconnect = await refreshRegistryCollections(); + + // Then + expect(reconnect).toEqual({ status: "reconnect" }); + + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ errors: [{ code: "registry_unavailable" }] }, 503), + ); + + // When + const unavailable = await refreshRegistryCollections(); + + // Then + expect(unavailable).toEqual({ status: "unavailable" }); + expect(unavailable).not.toHaveProperty("catalog"); + + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ errors: [{ code: "other_failure" }] }, 502), + ); + + // When + const generic = await refreshRegistryCollections(); + + // Then + expect(generic).toEqual({ status: "error" }); + }); + + it("keeps a transient access check failure retryable when refreshing collections", async () => { + // Given: the API cannot answer the permission check during a transient outage. + evaluateAccessMock.mockResolvedValueOnce({ status: "unknown" }); + + // When / Then: preserve the current page instead of treating the outage as revocation. + expect(await refreshRegistryCollections()).toEqual({ status: "error" }); + expect(fetchMock).not.toHaveBeenCalled(); + }); + + it("maps Registry 401 and 403 to access denial before any recovery classification", async () => { + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ errors: [{ code: "registry_key_rejected" }] }, 401), + ); + + // When + const credential = await refreshRegistryCredential(); + + // Then + expect(credential).toEqual({ status: "access_denied" }); + + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ errors: [{ code: "registry_unavailable" }] }, 403), + ); + + // When + const collections = await refreshRegistryCollections(); + + // Then + expect(collections).toEqual({ status: "access_denied" }); + expect(fetchMock).toHaveBeenCalledTimes(2); + }); + + it("rechecks access between separate actions after permission revocation", async () => { + // Given + evaluateAccessMock + .mockResolvedValueOnce({ status: "eligible" }) + .mockResolvedValueOnce({ status: "ineligible" }); + fetchMock.mockResolvedValueOnce(credentialResponse()); + + // When + const first = await refreshRegistryCredential(); + const second = await refreshRegistryCollections(); + + // Then + expect(first).toEqual({ status: "status", credential: activeCredential }); + expect(second).toEqual({ status: "access_denied" }); + expect(fetchMock).toHaveBeenCalledTimes(1); + expect(evaluateAccessMock).toHaveBeenCalledTimes(2); + }); + + it("returns the accepted validation task immediately without server-side polling", async () => { + // Given + const key = " registry-test-key "; + fetchMock + .mockResolvedValueOnce(credentialResponse(noCredential)) + .mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "tasks", id: "task-123" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/task-123" }, + }, + ), + ); + + // When + const result = await submitRegistryCredential(key); + + // Then + expect(result).toEqual({ + status: "submitted", + taskId: "task-123", + priorConfigured: false, + }); + expect(pollTaskUntilSettledMock).not.toHaveBeenCalled(); + expect(fetchMock).toHaveBeenCalledTimes(2); + expect(fetchMock).toHaveBeenNthCalledWith( + 2, + "https://api.test/api/v1/registry/credential", + expect.objectContaining({ + body: JSON.stringify({ + data: { + type: "registry-credentials", + attributes: { api_key: key.trim() }, + }, + }), + cache: "no-store", + method: "POST", + }), + ); + expect(JSON.stringify(result)).not.toContain(key); + }); + + it("marks an accepted replacement as superseding a configured credential", async () => { + // Given + fetchMock + .mockResolvedValueOnce(credentialResponse(activeCredential)) + .mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "tasks", id: "task-456" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/task-456" }, + }, + ), + ); + + // When + const result = await submitRegistryCredential("registry-replacement-key"); + + // Then + expect(result).toEqual({ + status: "submitted", + taskId: "task-456", + priorConfigured: true, + }); + expect(pollTaskUntilSettledMock).not.toHaveBeenCalled(); + }); + + it("re-reads credential and preserves authoritative My artifacts after disconnect", async () => { + // Given + fetchMock + .mockResolvedValueOnce(new Response(null, { status: 204 })) + .mockResolvedValueOnce(credentialResponse(noCredential)) + .mockResolvedValueOnce(tenantArtifactsResponse()); + + // When + const result = await disconnectRegistryCredential(); + + // Then + expect(result).toEqual({ + status: "disconnected", + credential: noCredential, + tenantArtifacts: [ + { + normalizedName: "prowler-aws", + versionSpec: "latest", + insertedAt: "2026-03-20T12:00:00Z", + }, + ], + }); + expect(fetchMock.mock.calls.map(([url]) => url)).toEqual([ + "https://api.test/api/v1/registry/credential", + "https://api.test/api/v1/registry/credential", + "https://api.test/api/v1/registry/artifacts", + ]); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + "https://api.test/api/v1/registry/credential", + expect.objectContaining({ cache: "no-store", method: "DELETE" }), + ); + }); + + it("rejects a task-binding mismatch without returning the key or a task", async () => { + // Given + const key = "registry-test-key"; + fetchMock + .mockResolvedValueOnce(credentialResponse(noCredential)) + .mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "tasks", id: "task-123" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/other-task" }, + }, + ), + ); + + // When + const result = await submitRegistryCredential(key); + + // Then + expect(result).toEqual({ status: "error" }); + expect(fetchMock).toHaveBeenCalledTimes(2); + expect(pollTaskUntilSettledMock).not.toHaveBeenCalled(); + expect(JSON.stringify(result)).not.toContain(key); + }); + + it("rejects malformed accepted task data without a task identity", async () => { + // Given + fetchMock + .mockResolvedValueOnce(credentialResponse(noCredential)) + .mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "not-a-task", id: "task-123" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/task-123" }, + }, + ), + ); + + // When + const result = await submitRegistryCredential("registry-test-key"); + + // Then + expect(result).toEqual({ status: "error" }); + expect(fetchMock).toHaveBeenCalledTimes(2); + expect(result).not.toHaveProperty("taskId"); + }); + + it("preserves an active credential after a rejected replacement", async () => { + // Given + const key = "registry-replacement-key"; + fetchMock + .mockResolvedValueOnce(credentialResponse(activeCredential)) + .mockResolvedValueOnce(jsonResponse({ errors: [] }, 500)); + + // When + const result = await submitRegistryCredential(key); + + // Then + expect(result).toEqual({ + status: "replacement_failed", + credential: activeCredential, + }); + expect(fetchMock).toHaveBeenCalledTimes(2); + expect(JSON.stringify(result)).not.toContain(key); + }); + + it("handles action authorization failures safely", async () => { + // Given + fetchMock + .mockResolvedValueOnce(credentialResponse(noCredential)) + .mockResolvedValueOnce(jsonResponse({ errors: [] }, 401)) + .mockResolvedValueOnce(jsonResponse({ errors: [] }, 403)); + + // When + const rejected = await submitRegistryCredential("registry-test-key"); + const disconnected = await disconnectRegistryCredential(); + + // Then + expect(rejected).toEqual({ status: "access_denied" }); + expect(disconnected).toEqual({ status: "access_denied" }); + expect(fetchMock).toHaveBeenCalledTimes(3); + }); +}); + +const installCatalogMock = vi.fn(); +describe("Registry artifact mutations", () => { + beforeEach(() => { + installCatalogMock.mockImplementation(() => + jsonResponse({ + data: [ + { + type: "registry-available-artifacts", + id: "later-guard", + attributes: { + has_provider: true, + is_builtin: false, + providers: ["acme"], + }, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 1 } }, + }), + ); + vi.stubGlobal("fetch", (url: string, options?: RequestInit) => + url.includes("/available-artifacts") + ? installCatalogMock(url, options) + : fetchMock(url, options), + ); + }); + + it.each([ + { has_provider: true, is_builtin: true }, + { has_provider: false, is_builtin: false }, + ])( + "refuses ineligible catalog entries before POST: %j", + async (attributes) => { + // Given + installCatalogMock.mockImplementation(() => + jsonResponse({ + data: [ + { + type: "registry-available-artifacts", + id: "later-guard", + attributes, + }, + ], + meta: { pagination: { page: 1, pages: 1, count: 1 } }, + }), + ); + // When + const result = await addRegistryArtifact({ + normalizedName: "later-guard", + }); + // Then + expect(result).toMatchObject({ status: "refused" }); + expect(fetchMock).not.toHaveBeenCalled(); + }, + ); + + it("returns an accepted Add task without reading My artifacts", async () => { + // Given + fetchMock.mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "tasks", id: "artifact-task" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/artifact-task" }, + }, + ), + ); + + // When + const result = await addRegistryArtifact({ + normalizedName: "later-guard", + versionSpec: " 2.0.0 ", + }); + + // Then + expect(result).toEqual({ status: "submitted", taskId: "artifact-task" }); + expect(fetchMock).toHaveBeenCalledTimes(1); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + "https://api.test/api/v1/registry/artifacts", + expect.objectContaining({ + body: JSON.stringify({ + data: { + type: "registry-artifacts", + attributes: { + normalized_name: "later-guard", + version_spec: "2.0.0", + }, + }, + }), + cache: "no-store", + method: "POST", + }), + ); + }); + + it("defaults Add to latest", async () => { + // Given + fetchMock.mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "tasks", id: "artifact-task" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/artifact-task" }, + }, + ), + ); + + // When + const result = await addRegistryArtifact({ normalizedName: "later-guard" }); + + // Then + expect(result).toEqual({ status: "submitted", taskId: "artifact-task" }); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + "https://api.test/api/v1/registry/artifacts", + expect.objectContaining({ + body: JSON.stringify({ + data: { + type: "registry-artifacts", + attributes: { + normalized_name: "later-guard", + version_spec: "latest", + }, + }, + }), + }), + ); + }); + + it("rejects invalid accepted task bindings without reading My artifacts", async () => { + // Given + const document = JSON.stringify({ + data: { type: "tasks", id: "artifact-task" }, + }); + fetchMock + .mockResolvedValueOnce( + new Response(JSON.stringify({ data: { type: "tasks" } }), { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/artifact-task" }, + }), + ) + .mockResolvedValueOnce(new Response(document, { status: 202 })) + .mockResolvedValueOnce( + new Response( + JSON.stringify({ data: { type: "other", id: "artifact-task" } }), + { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/artifact-task" }, + }, + ), + ) + .mockResolvedValueOnce( + new Response(document, { + status: 202, + headers: { "Content-Location": "/api/v1/tasks/other" }, + }), + ); + + // When + const outcomes = await Promise.all( + ["missing-id", "missing-location", "wrong-type", "wrong-location"].map( + () => addRegistryArtifact({ normalizedName: "later-guard" }), + ), + ); + + // Then + expect(outcomes).toEqual(Array(4).fill({ status: "error" })); + expect(fetchMock).toHaveBeenCalledTimes(4); + }); + + it("keeps a missing Registry credential synchronous", async () => { + // Given + fetchMock.mockResolvedValueOnce(jsonResponse({ errors: [] }, 409)); + + // When + const outcome = await addRegistryArtifact({ + normalizedName: "later-guard", + }); + + // Then + expect(outcome).toEqual({ status: "onboarding" }); + expect(fetchMock).toHaveBeenCalledOnce(); + }); + + it.each([ + ["registry_artifact_not_found", "This artifact is no longer available."], + ["version_yanked", "This version is no longer available."], + [ + "version_not_verified", + "This version is not verified and cannot be added.", + ], + ["version_not_processed", "This version is not ready to add yet."], + ["version_not_found", "This version is not available."], + ["no_installable_version", "No available version can be added."], + ])("keeps membership unchanged for %s", async (code, message) => { + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse( + { errors: [{ code }] }, + code === "registry_artifact_not_found" ? 404 : 400, + ), + ); + + // When + const result = await addRegistryArtifact({ + normalizedName: "later-guard", + versionSpec: "2.0.0", + }); + + // Then + expect(result).toEqual({ status: "refused", message }); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + + it("reports an in-use artifact when Remove returns 409 without refreshing membership", async () => { + // Given + fetchMock.mockResolvedValueOnce(new Response(null, { status: 409 })); + + // When + const result = await removeRegistryArtifact("aws-guard"); + + // Then + expect(result).toEqual({ status: "in_use" }); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + + it.each([ + [401, "access_denied"], + [403, "access_denied"], + [400, "error"], + [500, "error"], + ])("preserves the Remove failure for HTTP %s", async (status, expected) => { + // Given + fetchMock.mockResolvedValueOnce(new Response(null, { status })); + + // When + const result = await removeRegistryArtifact("aws-guard"); + + // Then + expect(result).toEqual({ status: expected }); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + + it("reports a Remove network failure without refreshing membership", async () => { + // Given + fetchMock.mockRejectedValueOnce(new TypeError("Failed to fetch")); + + // When + const result = await removeRegistryArtifact("aws-guard"); + + // Then + expect(result).toEqual({ status: "error" }); + expect(fetchMock).toHaveBeenCalledTimes(1); + }); + + it("encodes the deletion identity and confirms Remove after an absent refresh", async () => { + // Given + fetchMock + .mockResolvedValueOnce(new Response(null, { status: 204 })) + .mockResolvedValueOnce(jsonResponse({ data: [] })); + + // When + const result = await removeRegistryArtifact("guard/with space"); + + // Then + expect(result).toEqual({ status: "confirmed", tenantArtifacts: [] }); + expect(fetchMock).toHaveBeenNthCalledWith( + 1, + "https://api.test/api/v1/registry/artifacts/guard%2Fwith%20space", + expect.objectContaining({ cache: "no-store", method: "DELETE" }), + ); + }); + + it.each(["1.0.0", null, undefined])( + "does not confirm an update when the installed version is %j", + async (resolvedVersion) => { + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "template", + attributes: { + version_spec: "latest", + resolved_version: resolvedVersion, + }, + }, + ], + }), + ); + // When + const result = await confirmRegistryArtifactAddition("template", "1.1.0"); + // Then + expect(result).toEqual({ status: "refresh_failed" }); + }, + ); + + it("confirms an update only after reading its resolved target version", async () => { + // Given + fetchMock.mockResolvedValueOnce( + jsonResponse({ + data: [ + { + type: "registry-artifacts", + id: "template", + attributes: { version_spec: "latest", resolved_version: "1.1.0" }, + }, + ], + }), + ); + // When / Then + expect( + await confirmRegistryArtifactAddition("template", "1.1.0"), + ).toMatchObject({ + status: "confirmed", + tenantArtifacts: [ + { normalizedName: "template", resolvedVersion: "1.1.0" }, + ], + }); + }); + + it.each([ + [ + "Add", + () => addRegistryArtifact({ normalizedName: "later-guard" }), + { data: [] }, + { status: "error" }, + 1, + ], + [ + "Remove", + () => removeRegistryArtifact("later-guard"), + { + data: [ + { + type: "registry-artifacts", + id: "later-guard", + attributes: { version_spec: "latest" }, + }, + ], + }, + { status: "refresh_failed" }, + 2, + ], + ])( + "keeps membership unchanged when %s refresh contradicts acceptance", + async (_name, mutate, refreshedArtifacts, expected, calls) => { + // Given + fetchMock + .mockResolvedValueOnce(new Response(null, { status: 204 })) + .mockResolvedValueOnce(jsonResponse(refreshedArtifacts)); + + // When + const result = await mutate(); + + // Then + expect(result).toEqual(expected); + expect(fetchMock).toHaveBeenCalledTimes(calls); + }, + ); +}); diff --git a/ui/actions/registry/registry.ts b/ui/actions/registry/registry.ts new file mode 100644 index 0000000000..a67c83e57f --- /dev/null +++ b/ui/actions/registry/registry.ts @@ -0,0 +1,578 @@ +"use server"; + +import { z } from "zod"; + +import { auth } from "@/auth.config"; +import { apiBaseUrl } from "@/lib"; +import { REGISTRY_ACCESS } from "@/lib/registry/access"; +import { + evaluateRegistryAccess, + evaluateRegistryProviderAccess, +} from "@/lib/registry/access.server"; +import { isRegistryArtifactInstallable } from "@/lib/registry/artifacts"; +import { isActiveRegistryCredential } from "@/lib/registry/credential-task"; +import { + buildRegistryProviderOptions, + type RegistryProviderOption, +} from "@/lib/registry/provider-options"; +import { + REGISTRY_ARTIFACT_ACTION, + REGISTRY_ARTIFACT_REMOVAL, + REGISTRY_BOOTSTRAP_STATE, + REGISTRY_CATALOG, + REGISTRY_CREDENTIAL_ACTION, + REGISTRY_CREDENTIAL_READ, + REGISTRY_ENDPOINT, + REGISTRY_FAILURE, + REGISTRY_SUBMISSION, + type RegistryAddArtifactInput, + type RegistryArtifactRemovalResult, + type RegistryBootstrapResult, + type RegistryBootstrapState, + type RegistryCollectionsResult, + type RegistryCredentialActionResult, + type RegistryCredentialReadResult, + type RegistryCredentialStatus, + type RegistryCredentialSubmitResult, + type RegistryFailureResult, + type RegistryMutationResult, +} from "@/types/registry"; + +import { + adaptRegistryCredentialStatus, + adaptRegistryTenantArtifacts, + classifyRegistryFailure, + classifyRegistryMutationRefusal, + collectCompleteRegistryCatalog, + isRegistryCollection, + parseRegistryArtifactSubmission, + parseRegistryCredentialSubmission, + RegistryCatalogPageError, +} from "./registry.adapter"; + +const REGISTRY_REQUEST_TIMEOUT_MS = 15_000; + +async function getRegistryAccess(): Promise { + const accessToken = (await auth())?.accessToken; + const access = await evaluateRegistryAccess(accessToken); + return access.status === REGISTRY_ACCESS.ELIGIBLE && accessToken?.trim() + ? accessToken + : null; +} + +async function readRegistryResponse( + accessToken: string, + resource: string, + endpoint: (typeof REGISTRY_ENDPOINT)[keyof typeof REGISTRY_ENDPOINT], + credential: RegistryCredentialStatus | null = null, + searchParams?: URLSearchParams, +): Promise { + const url = new URL(`${apiBaseUrl}/registry/${resource}`); + if (searchParams) url.search = searchParams.toString(); + + let response: Response; + try { + response = await fetch(url.toString(), { + cache: "no-store", + signal: AbortSignal.timeout(REGISTRY_REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.api+json", + Authorization: `Bearer ${accessToken}`, + }, + }); + } catch { + return { status: REGISTRY_FAILURE.ERROR }; + } + if (response.ok) return response; + + return endpoint === REGISTRY_ENDPOINT.PROVIDERS || + endpoint === REGISTRY_ENDPOINT.AVAILABLE_ARTIFACTS + ? classifyDiscoveryFailure(response, endpoint, accessToken, credential) + : classifyRegistryFailure(response, endpoint, credential); +} + +async function readRegistryCredential(accessToken: string) { + const result = await readRegistryResponse( + accessToken, + "credential", + REGISTRY_ENDPOINT.CREDENTIAL, + ); + if (!(result instanceof Response)) return result; + + const credential = adaptRegistryCredentialStatus( + await result.json().catch(() => undefined), + ); + return credential + ? { status: REGISTRY_CREDENTIAL_READ.STATUS, credential } + : { status: REGISTRY_FAILURE.ERROR }; +} + +async function readRegistryTenantArtifacts(accessToken: string) { + const result = await readRegistryResponse( + accessToken, + "artifacts", + REGISTRY_ENDPOINT.MUTATION, + ); + if (!(result instanceof Response)) return result; + + const tenantArtifacts = adaptRegistryTenantArtifacts( + await result.json().catch(() => undefined), + ); + return tenantArtifacts + ? { status: "ready" as const, tenantArtifacts } + : { status: REGISTRY_FAILURE.ERROR }; +} + +async function classifyDiscoveryFailure( + response: Response, + endpoint: + | typeof REGISTRY_ENDPOINT.PROVIDERS + | typeof REGISTRY_ENDPOINT.AVAILABLE_ARTIFACTS, + accessToken: string, + credential: RegistryCredentialStatus | null, +) { + if (response.status === 409 && credential === null) { + const currentCredential = await readRegistryCredential(accessToken); + if (currentCredential.status === REGISTRY_FAILURE.ACCESS_DENIED) { + return currentCredential; + } + credential = + currentCredential.status === REGISTRY_CREDENTIAL_READ.STATUS + ? currentCredential.credential + : null; + } + return classifyRegistryFailure(response, endpoint, credential); +} + +async function readRegistryProviders( + accessToken: string, + credential: RegistryCredentialStatus | null, +) { + const result = await readRegistryResponse( + accessToken, + "providers", + REGISTRY_ENDPOINT.PROVIDERS, + credential, + ); + if (!(result instanceof Response)) return result; + const payload = await result.json().catch(() => undefined); + const metadata = z + .object({ + data: z.array( + z.object({ + id: z.string(), + attributes: z + .object({ + name: z.string().optional(), + logo_url: z.string().nullable().optional(), + }) + .optional(), + }), + ), + }) + .safeParse(payload); + return isRegistryCollection(payload) + ? { + status: "ready" as const, + providers: metadata.success + ? metadata.data.data.map((provider) => ({ + type: provider.id, + label: provider.attributes?.name || provider.id, + ...(provider.attributes?.logo_url + ? { logoUrl: provider.attributes.logo_url } + : {}), + })) + : [], + } + : { status: REGISTRY_FAILURE.ERROR }; +} + +export async function getInstalledRegistryProviderOptions(): Promise< + | { status: "ready"; options: RegistryProviderOption[] } + | { status: "access_denied" | "error" } +> { + const access = (await auth())?.accessToken; + const permission = await evaluateRegistryProviderAccess(access); + if (!access || permission.status !== REGISTRY_ACCESS.ELIGIBLE) + return { status: "access_denied" }; + const [catalog, installed, providers] = await Promise.all([ + readCompleteRegistryCatalog(access, null), + readRegistryTenantArtifacts(access), + readRegistryProviders(access, null), + ]); + if ( + [catalog.status, installed.status, providers.status].some( + (status) => status === REGISTRY_FAILURE.ACCESS_DENIED, + ) + ) + return { status: "access_denied" }; + if ( + catalog.status !== REGISTRY_CATALOG.COMPLETE || + installed.status !== "ready" || + providers.status !== "ready" + ) + return { status: "error" }; + return { + status: "ready", + options: buildRegistryProviderOptions( + catalog.artifacts, + installed.tenantArtifacts, + providers.providers, + ), + }; +} + +async function readCompleteRegistryCatalog( + accessToken: string, + credential: RegistryCredentialStatus | null, +) { + try { + return await collectCompleteRegistryCatalog(async (_page, searchParams) => { + const result = await readRegistryResponse( + accessToken, + "available-artifacts", + REGISTRY_ENDPOINT.AVAILABLE_ARTIFACTS, + credential, + searchParams, + ); + if (!(result instanceof Response)) + throw new RegistryCatalogPageError(result); + return result.json(); + }); + } catch (error) { + return error instanceof RegistryCatalogPageError + ? error.failure + : { status: REGISTRY_FAILURE.ERROR }; + } +} + +async function confirmRegistryMutation( + accessToken: string, + normalizedName: string, + shouldBePresent: boolean, + expectedVersion?: string, +): Promise { + const tenantArtifacts = await readRegistryTenantArtifacts(accessToken); + if (tenantArtifacts.status === REGISTRY_FAILURE.ACCESS_DENIED) + return tenantArtifacts; + if ( + tenantArtifacts.status !== "ready" || + tenantArtifacts.tenantArtifacts.some( + (artifact) => artifact.normalizedName === normalizedName, + ) !== shouldBePresent || + (expectedVersion !== undefined && + tenantArtifacts.tenantArtifacts.find( + (artifact) => artifact.normalizedName === normalizedName, + )?.resolvedVersion !== expectedVersion.trim()) + ) { + return { status: "refresh_failed" }; + } + return { + status: "confirmed", + tenantArtifacts: tenantArtifacts.tenantArtifacts, + }; +} + +function bootstrapReady( + state: RegistryBootstrapState, +): RegistryBootstrapResult { + return { status: REGISTRY_BOOTSTRAP_STATE.READY, state }; +} + +function bootstrapFailure( + failure: RegistryFailureResult, +): RegistryBootstrapResult { + if (failure.status === REGISTRY_FAILURE.ACCESS_DENIED) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + } + return bootstrapReady({ + status: + failure.status === REGISTRY_FAILURE.ONBOARDING + ? REGISTRY_BOOTSTRAP_STATE.ERROR + : failure.status, + }); +} + +export async function getRegistryBootstrap(): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + + const credentialRead = await readRegistryCredential(access); + if (credentialRead.status !== REGISTRY_CREDENTIAL_READ.STATUS) { + return bootstrapFailure(credentialRead); + } + const tenantArtifactsRead = await readRegistryTenantArtifacts(access); + if (tenantArtifactsRead.status !== "ready") { + return bootstrapFailure(tenantArtifactsRead); + } + + const { credential } = credentialRead; + const { tenantArtifacts } = tenantArtifactsRead; + if (!isActiveRegistryCredential(credential)) { + return bootstrapReady({ + status: credential.validationPending + ? REGISTRY_BOOTSTRAP_STATE.VALIDATION_PENDING + : REGISTRY_BOOTSTRAP_STATE.ONBOARDING, + credential, + tenantArtifacts, + }); + } + + const catalog = await readCompleteRegistryCatalog(access, credential); + if (catalog.status === REGISTRY_FAILURE.ACCESS_DENIED) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + } + if (catalog.status === REGISTRY_CATALOG.INCOMPLETE) { + return bootstrapReady({ + status: REGISTRY_BOOTSTRAP_STATE.INCOMPLETE, + catalog, + }); + } + if (catalog.status !== REGISTRY_CATALOG.COMPLETE) { + return bootstrapFailure(catalog); + } + + return bootstrapReady({ + status: REGISTRY_BOOTSTRAP_STATE.READY, + credential, + catalog, + tenantArtifacts, + }); +} + +export async function refreshRegistryCredential(): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + return readRegistryCredential(access); +} + +export async function refreshRegistryCollections(): Promise { + const access = (await auth())?.accessToken; + const permission = await evaluateRegistryAccess(access); + if (permission.status === REGISTRY_ACCESS.UNKNOWN) + return { status: REGISTRY_FAILURE.ERROR }; + if (permission.status !== REGISTRY_ACCESS.ELIGIBLE || !access?.trim()) + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + + const catalog = await readCompleteRegistryCatalog(access, null); + if (catalog.status !== REGISTRY_CATALOG.COMPLETE) return catalog; + const tenantArtifactsRead = await readRegistryTenantArtifacts(access); + return tenantArtifactsRead.status === "ready" + ? { + status: REGISTRY_CATALOG.COMPLETE, + catalog, + tenantArtifacts: tenantArtifactsRead.tenantArtifacts, + } + : tenantArtifactsRead; +} + +export async function addRegistryArtifact({ + normalizedName, + versionSpec, +}: RegistryAddArtifactInput): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED } as const; + if ( + typeof normalizedName !== "string" || + !normalizedName.trim() || + (versionSpec !== undefined && typeof versionSpec !== "string") + ) + return { status: REGISTRY_FAILURE.ERROR }; + const catalog = await readCompleteRegistryCatalog(access, null); + if (catalog.status !== REGISTRY_CATALOG.COMPLETE) { + return catalog.status === REGISTRY_CATALOG.INCOMPLETE + ? { status: REGISTRY_FAILURE.ERROR } + : catalog; + } + const artifact = catalog.artifacts.find( + (entry) => entry.normalizedName === normalizedName, + ); + if (!artifact || !isRegistryArtifactInstallable(artifact)) + return { + status: "refused", + message: "Only external provider artifacts can be added.", + }; + const selectedVersion = versionSpec?.trim() || "latest"; + + let response: Response; + try { + response = await fetch(`${apiBaseUrl}/registry/artifacts`, { + method: "POST", + cache: "no-store", + signal: AbortSignal.timeout(REGISTRY_REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.api+json", + "Content-Type": "application/vnd.api+json", + Authorization: `Bearer ${access}`, + }, + body: JSON.stringify({ + data: { + type: "registry-artifacts", + attributes: { + normalized_name: normalizedName, + version_spec: selectedVersion, + }, + }, + }), + }); + } catch { + return { status: REGISTRY_FAILURE.ERROR } as const; + } + if (response.status === 401 || response.status === 403) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED } as const; + } + if (response.status === 409) { + return { status: REGISTRY_FAILURE.ONBOARDING }; + } + if (!response.ok) { + return ( + (await classifyRegistryMutationRefusal(response)) ?? { + status: REGISTRY_FAILURE.ERROR, + } + ); + } + + const submission = await parseRegistryArtifactSubmission(response); + return submission.status === REGISTRY_SUBMISSION.PENDING + ? { status: REGISTRY_ARTIFACT_ACTION.SUBMITTED, taskId: submission.taskId } + : { status: REGISTRY_FAILURE.ERROR }; +} + +export async function confirmRegistryArtifactAddition( + normalizedName: string, + expectedVersion?: string, +): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + if ( + expectedVersion !== undefined && + (typeof expectedVersion !== "string" || !expectedVersion.trim()) + ) { + return { status: REGISTRY_FAILURE.ERROR }; + } + return confirmRegistryMutation(access, normalizedName, true, expectedVersion); +} + +export async function removeRegistryArtifact( + normalizedName: string, +): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + + let response: Response; + try { + response = await fetch( + `${apiBaseUrl}/registry/artifacts/${encodeURIComponent(normalizedName)}`, + { + method: "DELETE", + cache: "no-store", + signal: AbortSignal.timeout(REGISTRY_REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.api+json", + Authorization: `Bearer ${access}`, + }, + }, + ); + } catch { + return { status: REGISTRY_FAILURE.ERROR }; + } + if (response.status === 401 || response.status === 403) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + } + if (response.status === 409) { + return { status: REGISTRY_ARTIFACT_REMOVAL.IN_USE }; + } + if (!response.ok) return { status: REGISTRY_FAILURE.ERROR }; + + return confirmRegistryMutation(access, normalizedName, false); +} + +export async function submitRegistryCredential( + key: string, +): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + + const priorCredential = await readRegistryCredential(access); + if (priorCredential.status !== REGISTRY_CREDENTIAL_READ.STATUS) { + return priorCredential; + } + + let response: Response; + try { + response = await fetch(`${apiBaseUrl}/registry/credential`, { + method: "POST", + cache: "no-store", + signal: AbortSignal.timeout(REGISTRY_REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.api+json", + "Content-Type": "application/vnd.api+json", + Authorization: `Bearer ${access}`, + }, + body: JSON.stringify({ + data: { + type: "registry-credentials", + attributes: { api_key: key.trim() }, + }, + }), + }); + } catch { + return { status: REGISTRY_FAILURE.ERROR }; + } + if (response.status === 401 || response.status === 403) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + } + + // The task settles client-side through the task watcher; this action only + // hands back the verified task identity so the caller can watch it. + const submission = await parseRegistryCredentialSubmission(response); + if (submission.status !== REGISTRY_SUBMISSION.PENDING) { + return priorCredential.credential.configured + ? { + status: REGISTRY_CREDENTIAL_ACTION.REPLACEMENT_FAILED, + credential: priorCredential.credential, + } + : { status: REGISTRY_FAILURE.ERROR }; + } + + return { + status: REGISTRY_CREDENTIAL_ACTION.SUBMITTED, + taskId: submission.taskId, + priorConfigured: priorCredential.credential.configured, + }; +} + +export async function disconnectRegistryCredential(): Promise { + const access = await getRegistryAccess(); + if (!access) return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + + let response: Response; + try { + response = await fetch(`${apiBaseUrl}/registry/credential`, { + method: "DELETE", + cache: "no-store", + signal: AbortSignal.timeout(REGISTRY_REQUEST_TIMEOUT_MS), + headers: { + Accept: "application/vnd.api+json", + Authorization: `Bearer ${access}`, + }, + }); + } catch { + return { status: REGISTRY_FAILURE.ERROR }; + } + if (response.status === 401 || response.status === 403) { + return { status: REGISTRY_FAILURE.ACCESS_DENIED }; + } + + const credential = await readRegistryCredential(access); + const tenantArtifacts = await readRegistryTenantArtifacts(access); + if (credential.status !== REGISTRY_CREDENTIAL_READ.STATUS) return credential; + if (tenantArtifacts.status !== "ready") return tenantArtifacts; + if (!response.ok) return { status: REGISTRY_FAILURE.ERROR }; + + return { + status: REGISTRY_CREDENTIAL_ACTION.DISCONNECTED, + credential: credential.credential, + tenantArtifacts: tenantArtifacts.tenantArtifacts, + }; +} diff --git a/ui/actions/roles/roles.test.ts b/ui/actions/roles/roles.test.ts index 3b253cce58..6c79579b99 100644 --- a/ui/actions/roles/roles.test.ts +++ b/ui/actions/roles/roles.test.ts @@ -50,6 +50,7 @@ const makeRoleFormData = () => { formData.set("manage_scans", "false"); formData.set("manage_alerts", "true"); formData.set("manage_lighthouse_ai_configuration", "true"); + formData.set("manage_registry", "true"); formData.set("unlimited_visibility", "false"); return formData; }; @@ -73,6 +74,36 @@ describe("role actions", () => { vi.unstubAllEnvs(); }); + it("includes manage_registry when creating and updating a role in Prowler Cloud", async () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "true"); + + // When + await addRole(makeRoleFormData()); + const createAttributes = lastRequestBody().data.attributes; + await updateRole(makeRoleFormData(), "role-1"); + const updateAttributes = lastRequestBody().data.attributes; + + // Then + expect(createAttributes.manage_registry).toBe(true); + expect(updateAttributes.manage_registry).toBe(true); + }); + + it("omits manage_registry when creating and updating a role outside Prowler Cloud", async () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "false"); + + // When + await addRole(makeRoleFormData()); + const createAttributes = lastRequestBody().data.attributes; + await updateRole(makeRoleFormData(), "role-1"); + const updateAttributes = lastRequestBody().data.attributes; + + // Then + expect(createAttributes).not.toHaveProperty("manage_registry"); + expect(updateAttributes).not.toHaveProperty("manage_registry"); + }); + it("includes manage_alerts when creating a role in Prowler Cloud", async () => { // Given vi.stubEnv("UI_CLOUD_ENABLED", "true"); diff --git a/ui/actions/roles/roles.ts b/ui/actions/roles/roles.ts index 972d6d12e8..00302165e9 100644 --- a/ui/actions/roles/roles.ts +++ b/ui/actions/roles/roles.ts @@ -116,6 +116,8 @@ export const addRole = async (formData: FormData) => { formData.get("manage_alerts") === "true"; payload.data.attributes.manage_lighthouse_ai_configuration = formData.get("manage_lighthouse_ai_configuration") === "true"; + payload.data.attributes.manage_registry = + formData.get("manage_registry") === "true"; } // Add provider groups relationships only if there are items @@ -175,6 +177,8 @@ export const updateRole = async (formData: FormData, roleId: string) => { formData.get("manage_alerts") === "true"; payload.data.attributes.manage_lighthouse_ai_configuration = formData.get("manage_lighthouse_ai_configuration") === "true"; + payload.data.attributes.manage_registry = + formData.get("manage_registry") === "true"; } // Add provider groups relationships only if there are items diff --git a/ui/app/(prowler)/layout.tsx b/ui/app/(prowler)/layout.tsx index 4d0d06e092..a753c99c1a 100644 --- a/ui/app/(prowler)/layout.tsx +++ b/ui/app/(prowler)/layout.tsx @@ -6,6 +6,7 @@ import { ReactNode, Suspense } from "react"; import { getProviders } from "@/actions/providers"; import { getScansByState } from "@/actions/scans/scans"; +import { auth } from "@/auth.config"; import MainLayout from "@/components/layout/main-layout/main-layout"; import { OnboardingCheckpointWatcher, @@ -20,6 +21,8 @@ import { GlobalSidePanel } from "@/components/side-panel"; import { FeedbackSurvey } from "@/components/survey/feedback-survey"; import { fontMono, fontSans } from "@/config/fonts"; import { siteConfig } from "@/config/site"; +import { REGISTRY_ACCESS } from "@/lib/registry/access"; +import { evaluateRegistryAccess } from "@/lib/registry/access.server"; import { isCloud } from "@/lib/shared/env"; import { cn } from "@/lib/utils"; import { StoreInitializer } from "@/store/ui/store-initializer"; @@ -56,6 +59,13 @@ export default async function RootLayout({ // Skip Cloud-only onboarding fetches and orchestrators in OSS. const cloudEnabled = isCloud(); + // One-time server-side Registry gate per request: only an ELIGIBLE answer + // shows the sidebar entry; UNKNOWN and INELIGIBLE both hide it. Started + // here so it resolves in parallel with the Cloud onboarding fetches. + const registryAccessPromise = auth().then((session) => + evaluateRegistryAccess(session?.accessToken), + ); + // Fail-open: unknown scan state is treated as "has data" so the banner never blocks // progression on a fetch error. let hasCompletedScan = true; @@ -78,6 +88,9 @@ export default async function RootLayout({ : undefined; } + const registryEligible = + (await registryAccessPromise).status === REGISTRY_ACCESS.ELIGIBLE; + return ( @@ -98,7 +111,9 @@ export default async function RootLayout({ {/* Store uses boolean; gate receives tri-state to fail open on fetch errors. */} - + {cloudEnabled && ( <> diff --git a/ui/app/(prowler)/registry/page.tsx b/ui/app/(prowler)/registry/page.tsx new file mode 100644 index 0000000000..d5e3ab63de --- /dev/null +++ b/ui/app/(prowler)/registry/page.tsx @@ -0,0 +1,26 @@ +import { redirect } from "next/navigation"; + +import { getRegistryBootstrap } from "@/actions/registry/registry"; +import { RegistryExplorer } from "@/components/registry/registry-explorer"; +import { ContentLayout } from "@/components/shadcn/content-layout/content-layout"; +import { getRegistryPresentation } from "@/lib/registry/presentation"; +import { readEnv } from "@/lib/runtime-env"; +import { REGISTRY_FAILURE } from "@/types/registry"; + +export const dynamic = "force-dynamic"; + +export default async function RegistryPage() { + const bootstrap = await getRegistryBootstrap(); + if (bootstrap.status === REGISTRY_FAILURE.ACCESS_DENIED) redirect("/profile"); + + return ( + + + + ); +} diff --git a/ui/auth.config.test.ts b/ui/auth.config.test.ts index 5815f31496..0bb714cc93 100644 --- a/ui/auth.config.test.ts +++ b/ui/auth.config.test.ts @@ -39,6 +39,7 @@ const RESTRICTED_PERMISSIONS: RolePermissionAttributes = { manage_integrations: false, manage_billing: false, manage_alerts: false, + manage_registry: false, manage_lighthouse_ai_configuration: false, unlimited_visibility: false, }; @@ -46,6 +47,7 @@ const RESTRICTED_PERMISSIONS: RolePermissionAttributes = { const ELEVATED_PERMISSIONS: RolePermissionAttributes = { ...RESTRICTED_PERMISSIONS, manage_users: true, + manage_registry: true, manage_scans: true, }; @@ -174,6 +176,25 @@ describe("authConfig JWT callback", () => { }); }); + it("should default manage_registry to false when a sign-in user omits it", async () => { + // Given + const jwtCallback = authConfig.callbacks?.jwt; + if (!jwtCallback) throw new Error("JWT callback is not configured"); + + // When + const result = await jwtCallback({ + token: {}, + account: {} as Parameters[0]["account"], + user: { + accessToken: "access-token", + refreshToken: "refresh-token", + } as Parameters[0]["user"], + }); + + // Then + expect(result.user?.permissions.manage_registry).toBe(false); + }); + it("should report a tenant switch failure while preserving the current session", async () => { // Given vi.spyOn(console, "warn").mockImplementation(() => undefined); diff --git a/ui/auth.config.ts b/ui/auth.config.ts index c741534d24..f3ba8bbe18 100644 --- a/ui/auth.config.ts +++ b/ui/auth.config.ts @@ -61,6 +61,7 @@ const DEFAULT_PERMISSIONS: RolePermissionAttributes = { manage_billing: false, manage_alerts: false, manage_lighthouse_ai_configuration: false, + manage_registry: false, unlimited_visibility: false, }; diff --git a/ui/changelog.d/registry-private-cloud.added.md b/ui/changelog.d/registry-private-cloud.added.md new file mode 100644 index 0000000000..0f5b9fb6d3 --- /dev/null +++ b/ui/changelog.d/registry-private-cloud.added.md @@ -0,0 +1 @@ +Registry marketplace and external provider onboarding for Private Cloud, with permission-based access independent of billing, confirmed artifact installation, schema-driven credentials, connection checks, and scan launch diff --git a/ui/components/layout/app-sidebar/app-sidebar-content.test.tsx b/ui/components/layout/app-sidebar/app-sidebar-content.test.tsx index 911068b1cc..8e33a31b86 100644 --- a/ui/components/layout/app-sidebar/app-sidebar-content.test.tsx +++ b/ui/components/layout/app-sidebar/app-sidebar-content.test.tsx @@ -2,6 +2,7 @@ import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { useUIStore } from "@/store/ui/store"; import { CLOUD_UPGRADE_FEATURE } from "@/types/cloud-upgrade"; import { AppSidebarContent } from "./app-sidebar-content"; @@ -57,6 +58,7 @@ describe("AppSidebarContent", () => { openCloudUpgradeMock.mockClear(); openLaunchScanModalMock.mockClear(); useAppSidebarMode.setState({ mode: APP_SIDEBAR_MODE.BROWSE }); + useUIStore.setState({ registryEligible: false }); }); afterEach(() => { @@ -89,6 +91,32 @@ describe("AppSidebarContent", () => { expect(screen.getAllByText("Cloud").length).toBeGreaterThan(0); }); + it("shows Registry navigation when the server marked this request eligible", () => { + // Given + vi.stubEnv("UI_CLOUD_ENABLED", "true"); + useUIStore.setState({ registryEligible: true }); + + // When + render(); + + // Then + expect(screen.getByRole("link", { name: /Registry/ })).toHaveAttribute( + "href", + "/registry", + ); + }); + + it("hides Registry navigation without a server eligibility decision", () => { + // Given / When + vi.stubEnv("UI_CLOUD_ENABLED", "true"); + render(); + + // Then + expect( + screen.queryByRole("link", { name: /Registry/ }), + ).not.toBeInTheDocument(); + }); + it("keeps the existing Lighthouse chat sidebar in Cloud Chat mode", () => { // Given vi.stubEnv("UI_CLOUD_ENABLED", "true"); diff --git a/ui/components/layout/app-sidebar/app-sidebar-content.tsx b/ui/components/layout/app-sidebar/app-sidebar-content.tsx index 8d5e869793..f157e2f7ae 100644 --- a/ui/components/layout/app-sidebar/app-sidebar-content.tsx +++ b/ui/components/layout/app-sidebar/app-sidebar-content.tsx @@ -8,6 +8,7 @@ import { ProwlerBrand } from "@/components/icons"; import { useAuth } from "@/hooks"; import { useRuntimeConfig } from "@/hooks/use-runtime-config"; import { isCloud } from "@/lib/shared/env"; +import { useUIStore } from "@/store/ui/store"; import { useAppSidebarMode } from "./app-sidebar-mode-store"; import { AppSidebarModeToggle } from "./app-sidebar-mode-toggle"; @@ -24,6 +25,8 @@ interface AppSidebarContentProps { export function AppSidebarContent({ onSelect }: AppSidebarContentProps) { const pathname = usePathname(); const { permissions } = useAuth(); + // One-time server decision per request, seeded by the root layout. + const registryEligible = useUIStore((state) => state.registryEligible); const { apiDocsUrl, cloudBillingEnabled } = useRuntimeConfig(); const mode = useAppSidebarMode((state) => state.mode); const isCloudEnvironment = isCloud(); @@ -31,6 +34,7 @@ export function AppSidebarContent({ onSelect }: AppSidebarContentProps) { pathname, apiDocsUrl, cloudBillingEnabled, + registryEligible, permissions, }); const showChat = isCloudEnvironment && mode === APP_SIDEBAR_MODE.CHAT; diff --git a/ui/components/layout/app-sidebar/navigation-config.ts b/ui/components/layout/app-sidebar/navigation-config.ts index 05ff31abae..aa0904d3b9 100644 --- a/ui/components/layout/app-sidebar/navigation-config.ts +++ b/ui/components/layout/app-sidebar/navigation-config.ts @@ -5,6 +5,7 @@ import { GitBranch, LayoutGrid, MessageCircleQuestion, + Package, Settings, ShieldCheck, SquareChartGantt, @@ -32,6 +33,7 @@ interface NavigationConfigOptions { pathname: string; apiDocsUrl?: string | null; cloudBillingEnabled?: boolean; + registryEligible?: boolean; permissions?: RolePermissionAttributes; } @@ -108,6 +110,7 @@ export function getNavigationConfig({ pathname, apiDocsUrl = null, cloudBillingEnabled = false, + registryEligible = false, permissions, }: NavigationConfigOptions): NavigationSection[] { const isCloudEnvironment = isCloud(); @@ -180,6 +183,18 @@ export function getNavigationConfig({ icon: Warehouse, active: isRouteActive(pathname, "/resources"), }, + ...(registryEligible + ? [ + { + kind: NAVIGATION_ITEM_KIND.LINK, + href: "/registry", + label: "Registry", + icon: Package, + active: isRouteActive(pathname, "/registry"), + highlight: true, + } as const, + ] + : []), ], }, { diff --git a/ui/components/providers/radio-group-provider.test.tsx b/ui/components/providers/radio-group-provider.test.tsx new file mode 100644 index 0000000000..34987d5a41 --- /dev/null +++ b/ui/components/providers/radio-group-provider.test.tsx @@ -0,0 +1,134 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { useForm } from "react-hook-form"; +import { describe, expect, it } from "vitest"; + +import type { RegistryProviderOption } from "@/lib/registry/provider-options"; +import type { AddProviderFormValues } from "@/types/formSchemas"; + +import { RadioGroupProvider } from "./radio-group-provider"; + +function Selector({ + registryOptions = [{ type: "acme", label: "Acme Cloud" }], +}: { + registryOptions?: RegistryProviderOption[]; +}) { + const form = useForm(); + return ( + + ); +} + +describe("provider selector", () => { + it("preserves selected provider across tabs and supports searching by type", async () => { + // Given + const user = userEvent.setup(); + render( + , + ); + expect(screen.getByRole("tab", { name: "All providers" })).toHaveAttribute( + "aria-selected", + "true", + ); + await user.click( + screen.getByRole("option", { name: /Amazon Web Services/ }), + ); + + // When + await user.click(screen.getByRole("tab", { name: "Registry" })); + await user.type( + screen.getByRole("textbox", { name: "Search providers" }), + " ACME_SLUG ", + ); + + // Then + expect( + screen.getByRole("option", { name: /Acme Cloud Registry/ }), + ).toBeVisible(); + + // When + await user.click(screen.getByRole("button", { name: "Clear search" })); + await user.click(screen.getByRole("tab", { name: "All providers" })); + + // Then + expect( + screen.getByRole("option", { name: /Amazon Web Services/ }), + ).toHaveAttribute("aria-selected", "true"); + }); + + it("keeps both tabs available when no Registry providers are installed", async () => { + // Given + const user = userEvent.setup(); + const { rerender } = render(); + + // When + await user.click(screen.getByRole("tab", { name: "Registry" })); + + // Then + expect(screen.getByText("No Registry providers available.")).toBeVisible(); + expect(screen.getByRole("tab", { name: "All providers" })).toBeEnabled(); + + // When / Then: discovery can refresh the installed options. + rerender(); + expect( + screen.getByRole("option", { name: /Acme Cloud Registry/ }), + ).toBeVisible(); + rerender(); + expect(screen.queryByRole("option")).not.toBeInTheDocument(); + expect(screen.getByText("No Registry providers available.")).toBeVisible(); + }); + + it("filters Registry providers and preserves search across tabs", async () => { + // Given + const user = userEvent.setup(); + render(); + + // When + await user.click(screen.getByRole("tab", { name: "Registry" })); + + // Then + expect( + screen.getByRole("option", { name: /Acme Cloud Registry/ }), + ).toBeVisible(); + expect( + screen.queryByRole("option", { name: /Amazon Web Services/ }), + ).not.toBeInTheDocument(); + + // When + await user.type( + screen.getByRole("textbox", { name: "Search providers" }), + "amazon", + ); + expect( + screen.getByText('No providers found matching "amazon"'), + ).toBeVisible(); + await user.click(screen.getByRole("tab", { name: "All providers" })); + + // Then + expect( + screen.getByRole("textbox", { name: "Search providers" }), + ).toHaveValue("amazon"); + expect( + screen.getByRole("option", { name: /Amazon Web Services/ }), + ).toBeVisible(); + expect( + screen.queryByRole("option", { name: /Acme Cloud Registry/ }), + ).not.toBeInTheDocument(); + }); + + it("adds Registry-labelled providers alongside the incorporated options", () => { + render(); + expect( + screen.getByRole("option", { name: /Acme Cloud Registry/ }), + ).toBeVisible(); + expect( + screen.getByRole("option", { name: /Amazon Web Services/ }), + ).toBeVisible(); + }); +}); diff --git a/ui/components/providers/radio-group-provider.tsx b/ui/components/providers/radio-group-provider.tsx index de8d941f3a..0da4bf2d83 100644 --- a/ui/components/providers/radio-group-provider.tsx +++ b/ui/components/providers/radio-group-provider.tsx @@ -2,117 +2,38 @@ import { FC, useState } from "react"; import { Control, Controller } from "react-hook-form"; -import { z } from "zod"; - -import { SearchInput } from "@/components/shadcn"; -import { FormMessage } from "@/components/shadcn/form"; -import { cn } from "@/lib/utils"; -import { addProviderFormSchema } from "@/types"; import { - AlibabaCloudProviderBadge, - AWSProviderBadge, - AzureProviderBadge, - CloudflareProviderBadge, - GCPProviderBadge, - GitHubProviderBadge, - GoogleWorkspaceProviderBadge, - IacProviderBadge, - ImageProviderBadge, - KS8ProviderBadge, - M365ProviderBadge, - MongoDBAtlasProviderBadge, - OktaProviderBadge, - OpenStackProviderBadge, - OracleCloudProviderBadge, - VercelProviderBadge, -} from "../icons/providers-badge"; + ProviderTypeIcon, + PROVIDER_TYPE_DATA, +} from "@/components/icons/providers-badge/provider-type-icon"; +import { Badge, SearchInput } from "@/components/shadcn"; +import { + Avatar, + AvatarFallback, + AvatarImage, +} from "@/components/shadcn/avatar"; +import { FormMessage } from "@/components/shadcn/form"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "@/components/shadcn/tabs/tabs"; +import type { RegistryProviderOption } from "@/lib/registry/provider-options"; +import { cn } from "@/lib/utils"; +import type { AddProviderFormValues } from "@/types/formSchemas"; -const PROVIDERS = [ - { - value: "aws", - label: "Amazon Web Services", - badge: AWSProviderBadge, - }, - { - value: "gcp", - label: "Google Cloud Platform", - badge: GCPProviderBadge, - }, - { - value: "azure", - label: "Microsoft Azure", - badge: AzureProviderBadge, - }, - { - value: "m365", - label: "Microsoft 365", - badge: M365ProviderBadge, - }, - { - value: "mongodbatlas", - label: "MongoDB Atlas", - badge: MongoDBAtlasProviderBadge, - }, - { - value: "kubernetes", - label: "Kubernetes", - badge: KS8ProviderBadge, - }, - { - value: "github", - label: "GitHub", - badge: GitHubProviderBadge, - }, - { - value: "googleworkspace", - label: "Google Workspace", - badge: GoogleWorkspaceProviderBadge, - }, - { - value: "iac", - label: "Infrastructure as Code", - badge: IacProviderBadge, - }, - { - value: "image", - label: "Container Registry", - badge: ImageProviderBadge, - }, - { - value: "oraclecloud", - label: "Oracle Cloud Infrastructure", - badge: OracleCloudProviderBadge, - }, - { - value: "alibabacloud", - label: "Alibaba Cloud", - badge: AlibabaCloudProviderBadge, - }, - { - value: "cloudflare", - label: "Cloudflare", - badge: CloudflareProviderBadge, - }, - { - value: "openstack", - label: "OpenStack", - badge: OpenStackProviderBadge, - }, - { - value: "vercel", - label: "Vercel", - badge: VercelProviderBadge, - }, - { - value: "okta", - label: "Okta", - badge: OktaProviderBadge, - }, -] as const; +const PROVIDERS = Object.entries(PROVIDER_TYPE_DATA).map( + ([value, { label }]) => ({ value, label }), +); + +const PROVIDER_TAB = { ALL: "all", REGISTRY: "registry" } as const; +type ProviderTab = (typeof PROVIDER_TAB)[keyof typeof PROVIDER_TAB]; interface RadioGroupProviderProps { - control: Control>; + control: Control; + registryOptions?: RegistryProviderOption[]; isInvalid: boolean; errorMessage?: string; } @@ -121,25 +42,53 @@ export const RadioGroupProvider: FC = ({ control, isInvalid, errorMessage, + registryOptions = [], }) => { const [searchTerm, setSearchTerm] = useState(""); + const [activeTab, setActiveTab] = useState(PROVIDER_TAB.ALL); + const options = [ + ...PROVIDERS.map((provider) => ({ + value: provider.value as string, + label: provider.label as string, + registry: false, + logoUrl: undefined as string | undefined, + })), + ...registryOptions.map((provider) => ({ + value: provider.type, + label: provider.label, + registry: true, + logoUrl: provider.logoUrl, + })), + ]; + const tabProviders = + activeTab === PROVIDER_TAB.REGISTRY + ? options.filter((provider) => provider.registry) + : options; const lowerSearch = searchTerm.trim().toLowerCase(); const filteredProviders = lowerSearch - ? PROVIDERS.filter( + ? tabProviders.filter( (provider) => provider.label.toLowerCase().includes(lowerSearch) || provider.value.toLowerCase().includes(lowerSearch), ) - : PROVIDERS; + : tabProviders; return ( ( -
    -
    + setActiveTab(value as ProviderTab)} + > + + All providers + Registry + +
    = ({ />
    -
    +
    = ({ > {filteredProviders.length > 0 ? ( filteredProviders.map((provider) => { - const BadgeComponent = provider.badge; const isSelected = field.value === provider.value; return ( @@ -165,6 +113,7 @@ export const RadioGroupProvider: FC = ({ key={provider.value} type="button" role="option" + aria-label={`${provider.label}${provider.registry ? " Registry" : ""}`} aria-selected={isSelected} onClick={() => field.onChange(provider.value)} className={cn( @@ -183,28 +132,54 @@ export const RadioGroupProvider: FC = ({
    - + {provider.registry ? ( + + + + + + + ) : ( + + )} {provider.label} + {provider.registry && ( + Registry + )}
    ); }) ) : (

    - No providers found matching "{searchTerm}" + {lowerSearch ? ( + <>No providers found matching "{searchTerm}" + ) : ( + "No Registry providers available." + )}

    )}
    -
    + {errorMessage && ( {errorMessage} )} -
    + )} /> ); diff --git a/ui/components/providers/table/column-providers.tsx b/ui/components/providers/table/column-providers.tsx index 78c59ac764..548dda2e82 100644 --- a/ui/components/providers/table/column-providers.tsx +++ b/ui/components/providers/table/column-providers.tsx @@ -251,7 +251,7 @@ export function getColumnProviders( entityId={provider.attributes.uid} nameAction={ provider.attributes.is_dynamic ? ( - Custom + Registry ) : undefined } /> diff --git a/ui/components/providers/table/data-table-row-actions.test.tsx b/ui/components/providers/table/data-table-row-actions.test.tsx index 5fa6f3f409..c65863abd2 100644 --- a/ui/components/providers/table/data-table-row-actions.test.tsx +++ b/ui/components/providers/table/data-table-row-actions.test.tsx @@ -1,3 +1,17 @@ +vi.mock("@/actions/providers/registry-provider", () => ({ + addRegistryProvider: vi.fn(), +})); +vi.mock("@/actions/registry/registry", () => ({ + getInstalledRegistryProviderOptions: vi + .fn() + .mockResolvedValue({ status: "access_denied" }), +})); +vi.mock("@/actions/providers/provider-schemas", () => ({ + getProviderSchemas: vi.fn(), +})); +vi.mock("@/actions/providers/dynamic-provider-credentials", () => ({ + saveDynamicProviderCredentials: vi.fn(), +})); import { Row } from "@tanstack/react-table"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; @@ -327,7 +341,7 @@ describe("DataTableRowActions", () => { expect(screen.queryByText("Update Credentials")).not.toBeInTheDocument(); }); - it("allows rename/delete and operational actions for a dynamic provider but hides credential management", async () => { + it("allows credential editing and operational actions for a dynamic provider", async () => { // Given a dynamic provider outside the configurable set, with the advanced // schedule capability enabled (so Edit Scan Schedule can show). const user = userEvent.setup(); @@ -354,9 +368,9 @@ describe("DataTableRowActions", () => { expect(screen.getByText("Test Connection")).toBeInTheDocument(); expect(screen.getByText("View Scan Jobs")).toBeInTheDocument(); expect(screen.getByText("Edit Scan Schedule")).toBeInTheDocument(); - // ...but credential management is hidden (no bespoke wizard for dynamic types) + // Existing dynamic accounts use the same wizard with schema-based credentials. expect(screen.queryByText("Add Credentials")).not.toBeInTheDocument(); - expect(screen.queryByText("Update Credentials")).not.toBeInTheDocument(); + expect(screen.getByText("Update Credentials")).toBeInTheDocument(); }); it("navigates to the provider-filtered scan jobs from View Scan Jobs", async () => { diff --git a/ui/components/providers/table/data-table-row-actions.tsx b/ui/components/providers/table/data-table-row-actions.tsx index 1866a44f73..bcbbd8e583 100644 --- a/ui/components/providers/table/data-table-row-actions.tsx +++ b/ui/components/providers/table/data-table-row-actions.tsx @@ -52,7 +52,6 @@ import { OrgFlowType, } from "@/types/organizations"; import { PROVIDER_WIZARD_MODE } from "@/types/provider-wizard"; -import { isConfigurableProvider } from "@/types/providers"; import { isProvidersOrganizationRow, PROVIDERS_GROUP_KIND, @@ -355,8 +354,7 @@ export function DataTableRowActions({ const provider = isOrganizationRow ? null : rowData; const providerId = provider?.id ?? ""; const providerType = provider?.attributes.provider ?? ""; - // Only predefined providers can manage credentials from the UI - const canManageCredentials = isConfigurableProvider(providerType); + const canManageCredentials = Boolean(providerType); const providerUid = provider?.attributes.uid ?? ""; const providerAlias = provider?.attributes.alias ?? null; const providerSecretId = provider?.relationships.secret.data?.id ?? null; diff --git a/ui/components/providers/wizard/provider-wizard-modal.test.tsx b/ui/components/providers/wizard/provider-wizard-modal.test.tsx new file mode 100644 index 0000000000..40414c3688 --- /dev/null +++ b/ui/components/providers/wizard/provider-wizard-modal.test.tsx @@ -0,0 +1,230 @@ +import { act, render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import { Toaster } from "@/components/shadcn/toast/Toaster"; +import { resetToasts } from "@/components/shadcn/toast/use-toast"; +import { useProviderWizardStore } from "@/store/provider-wizard/store"; + +import { ProviderWizardModal } from "./provider-wizard-modal"; + +const { addRegistryProvider, getInstalledRegistryProviderOptions } = vi.hoisted( + () => ({ + addRegistryProvider: vi.fn(), + getInstalledRegistryProviderOptions: vi.fn(), + }), +); + +vi.mock("next/navigation", () => ({ + useRouter: () => ({ refresh: vi.fn(), push: vi.fn() }), +})); +vi.mock("@/actions/providers/providers", () => ({ addProvider: vi.fn() })); +vi.mock("@/actions/providers/registry-provider", () => ({ + addRegistryProvider, +})); +vi.mock("@/actions/registry/registry", () => ({ + getInstalledRegistryProviderOptions, +})); +vi.mock( + "@/components/providers/workflow/forms", + async () => import("../workflow/forms/connect-account-form"), +); +vi.mock("@/hooks/use-scroll-hint", () => ({ + useScrollHint: () => ({ showScrollHint: false }), +})); +vi.mock("@/lib/tours/use-driver-tour", () => ({ + advanceActiveTour: vi.fn(), + endActiveTour: vi.fn(), +})); +vi.mock("./steps/credentials-step", () => ({ + CredentialsStep: () =>

    Credential details

    , +})); +vi.mock("./steps/test-connection-step", () => ({ + TestConnectionStep: () => null, +})); +vi.mock("./steps/launch-step", () => ({ LaunchStep: () => null })); +vi.mock("../organizations/azure-org-setup-form", () => ({ + AzureOrgSetupForm: () => null, +})); +vi.mock("../organizations/gcp-org-setup-form", () => ({ + GcpOrgSetupForm: () => null, +})); +vi.mock("../organizations/org-setup-form", () => ({ + OrgSetupForm: () => null, +})); +vi.mock("../organizations/org-account-selection", () => ({ + OrgAccountSelection: () => null, +})); +vi.mock("../organizations/org-launch-scan", () => ({ + OrgLaunchScan: () => null, +})); + +const createdAccount = { + data: { + id: "account", + attributes: { provider: "acme", uid: "acme-account", alias: null }, + }, +}; + +async function enterAccountDetails() { + const user = userEvent.setup(); + render( + <> + + + , + ); + await user.click( + await screen.findByRole("option", { name: "Acme Cloud Registry" }), + ); + await user.type( + screen.getByRole("textbox", { name: "Provider UID" }), + "acme-account", + ); + await waitFor(() => + expect(screen.getByRole("button", { name: "Next" })).toBeEnabled(), + ); + return user; +} + +describe("provider wizard account creation", () => { + beforeEach(() => { + useProviderWizardStore.getState().reset(); + resetToasts(); + getInstalledRegistryProviderOptions.mockResolvedValue({ + status: "ready", + options: [{ type: "acme", label: "Acme Cloud" }], + }); + }); + + it("shows progress, blocks repeat clicks, and advances after creation", async () => { + // Given + let resolveCreation!: (value: typeof createdAccount) => void; + addRegistryProvider.mockImplementationOnce( + () => + new Promise((resolve) => { + resolveCreation = resolve; + }), + ); + const user = await enterAccountDetails(); + + // When + await user.click(screen.getByRole("button", { name: "Next" })); + + // Then + const pending = await screen.findByRole("button", { + name: "Creating provider...", + }); + expect(pending).toBeDisabled(); + expect(pending).toHaveAttribute("aria-busy", "true"); + expect(screen.getByRole("button", { name: "Back" })).toBeDisabled(); + await user.dblClick(pending); + expect(addRegistryProvider).toHaveBeenCalledOnce(); + + // When / Then + await act(async () => resolveCreation(createdAccount)); + expect(await screen.findByText("Credential details")).toBeVisible(); + }); + + it("restores Next after a failed creation and retries the same account", async () => { + // Given + const failure = { errors: [{ detail: "Creation failed. Try again." }] }; + let resolveCreation!: (value: typeof failure) => void; + addRegistryProvider + .mockImplementationOnce( + () => + new Promise((resolve) => { + resolveCreation = resolve; + }), + ) + .mockResolvedValueOnce(createdAccount); + const user = await enterAccountDetails(); + + // When + await user.click(screen.getByRole("button", { name: "Next" })); + await screen.findByRole("button", { name: "Creating provider..." }); + await act(async () => resolveCreation(failure)); + + // Then + expect(await screen.findByText(failure.errors[0].detail)).toBeVisible(); + const next = screen.getByRole("button", { name: "Next" }); + await waitFor(() => expect(next).toBeEnabled()); + expect(next).not.toHaveAttribute("aria-busy", "true"); + expect(screen.getByRole("button", { name: "Back" })).toBeEnabled(); + expect(screen.getByRole("textbox", { name: "Provider UID" })).toHaveValue( + "acme-account", + ); + + // When / Then + await user.click(next); + expect(await screen.findByText("Credential details")).toBeVisible(); + expect(addRegistryProvider).toHaveBeenCalledTimes(2); + expect( + Object.fromEntries(addRegistryProvider.mock.calls[1][0]), + ).toMatchObject({ providerType: "acme", providerUid: "acme-account" }); + }); + + it("shows provider conflicts in the account step and allows retrying", async () => { + // Given + const detail = + "The artifact 'acme' is not installed on this deployment yet. Install it again and retry."; + addRegistryProvider + .mockResolvedValueOnce({ + errors: [ + { + status: "409", + detail, + source: { pointer: "/data/attributes/provider" }, + }, + ], + }) + .mockResolvedValueOnce(createdAccount); + const user = await enterAccountDetails(); + + // When + await user.click(screen.getByRole("button", { name: "Next" })); + + // Then + expect(await screen.findByRole("alert")).toHaveTextContent(detail); + expect(screen.getByRole("textbox", { name: "Provider UID" })).toHaveValue( + "acme-account", + ); + const next = await screen.findByRole("button", { name: "Next" }); + await waitFor(() => expect(next).toBeEnabled()); + expect(screen.getByRole("button", { name: "Back" })).toBeEnabled(); + + // When / Then: the provider becomes available and the same account retries. + await user.click(next); + expect(await screen.findByText("Credential details")).toBeVisible(); + expect(screen.queryByText(detail)).not.toBeInTheDocument(); + expect(addRegistryProvider).toHaveBeenCalledTimes(2); + }); + + it("keeps native providers available during a Registry discovery error and retries", async () => { + // Given + getInstalledRegistryProviderOptions.mockRejectedValueOnce( + new Error("Unavailable"), + ); + const user = userEvent.setup(); + render(); + await screen.findByText("Registry providers could not be loaded"); + expect( + screen.getByRole("option", { name: /Amazon Web Services/ }), + ).toBeVisible(); + + // When + await user.click(screen.getByRole("tab", { name: "Registry" })); + expect(screen.getByText("No Registry providers available.")).toBeVisible(); + await user.click( + screen.getByRole("button", { name: "Retry Registry providers" }), + ); + + // Then + expect( + await screen.findByRole("option", { name: "Acme Cloud Registry" }), + ).toBeVisible(); + expect( + screen.queryByText("Registry providers could not be loaded"), + ).not.toBeInTheDocument(); + }); +}); diff --git a/ui/components/providers/wizard/provider-wizard-modal.tsx b/ui/components/providers/wizard/provider-wizard-modal.tsx index d39a491b17..fab1a4440f 100644 --- a/ui/components/providers/wizard/provider-wizard-modal.tsx +++ b/ui/components/providers/wizard/provider-wizard-modal.tsx @@ -1,6 +1,6 @@ "use client"; -import { ExternalLink, Info } from "lucide-react"; +import { ExternalLink, Info, Loader2 } from "lucide-react"; import { AzureOrgSetupForm } from "@/components/providers/organizations/azure-org-setup-form"; import { GcpOrgSetupForm } from "@/components/providers/organizations/gcp-org-setup-form"; @@ -405,7 +405,11 @@ export function ProviderWizardModal({ : "button" } form={resolvedFooterConfig.actionFormId} - disabled={resolvedFooterConfig.actionDisabled} + disabled={ + resolvedFooterConfig.actionDisabled || + resolvedFooterConfig.actionLoading + } + aria-busy={resolvedFooterConfig.actionLoading || undefined} onClick={ resolvedFooterConfig.actionType === WIZARD_FOOTER_ACTION_TYPE.BUTTON @@ -413,6 +417,9 @@ export function ProviderWizardModal({ : undefined } > + {resolvedFooterConfig.actionLoading && ( + + )} {resolvedFooterConfig.actionLabel} )} diff --git a/ui/components/providers/wizard/steps/connect-step.tsx b/ui/components/providers/wizard/steps/connect-step.tsx index a26013aba3..649f0d1562 100644 --- a/ui/components/providers/wizard/steps/connect-step.tsx +++ b/ui/components/providers/wizard/steps/connect-step.tsx @@ -63,6 +63,7 @@ export function ConnectStep({ onBack: () => backHandlerRef.current?.(), showAction: uiState.showAction, actionLabel: uiState.actionLabel, + actionLoading: uiState.isLoading, actionDisabled: uiState.actionDisabled || uiState.isLoading, actionType: WIZARD_FOOTER_ACTION_TYPE.SUBMIT, actionFormId: formId, diff --git a/ui/components/providers/wizard/steps/credentials-step.test.tsx b/ui/components/providers/wizard/steps/credentials-step.test.tsx index 7f4610b212..8fa035ea33 100644 --- a/ui/components/providers/wizard/steps/credentials-step.test.tsx +++ b/ui/components/providers/wizard/steps/credentials-step.test.tsx @@ -1,3 +1,6 @@ +vi.mock("./dynamic-credentials-step", () => ({ + DynamicCredentialsStep: () =>
    dynamic-credentials-form
    , +})); import { render, screen } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; diff --git a/ui/components/providers/wizard/steps/credentials-step.tsx b/ui/components/providers/wizard/steps/credentials-step.tsx index 371f356d30..75836a25e3 100644 --- a/ui/components/providers/wizard/steps/credentials-step.tsx +++ b/ui/components/providers/wizard/steps/credentials-step.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from "react"; import { getProviderFormType } from "@/lib/provider-helpers"; import { useProviderWizardStore } from "@/store/provider-wizard/store"; -import { ProviderType } from "@/types/providers"; +import { isKnownProviderType, ProviderType } from "@/types/providers"; import { AddViaCredentialsForm, @@ -23,6 +23,7 @@ import { SelectViaGitHub } from "../../workflow/forms/select-credentials-type/gi import { SelectViaM365 } from "../../workflow/forms/select-credentials-type/m365"; import { UpdateViaServiceAccountForm } from "../../workflow/forms/update-via-service-account-key-form"; +import { DynamicCredentialsStep } from "./dynamic-credentials-step"; import { WIZARD_FOOTER_ACTION_TYPE, WizardFooterConfig, @@ -34,7 +35,22 @@ interface CredentialsStepProps { onFooterChange: (config: WizardFooterConfig) => void; } -export function CredentialsStep({ +export function CredentialsStep(props: CredentialsStepProps) { + const providerId = useProviderWizardStore((state) => state.providerId); + const providerType = useProviderWizardStore((state) => state.providerType); + if (providerId && providerType && !isKnownProviderType(providerType)) { + return ( + + ); + } + return ; +} + +function BuiltinCredentialsStep({ onNext, onBack, onFooterChange, diff --git a/ui/components/providers/wizard/steps/dynamic-credentials-step.test.tsx b/ui/components/providers/wizard/steps/dynamic-credentials-step.test.tsx new file mode 100644 index 0000000000..ce28a075b1 --- /dev/null +++ b/ui/components/providers/wizard/steps/dynamic-credentials-step.test.tsx @@ -0,0 +1,365 @@ +import { + act, + fireEvent, + render, + screen, + waitFor, +} from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; + +import openaiSchema from "@/lib/provider-credentials/fixtures/openai-credential-schema.json"; +import templateSchema from "@/lib/provider-credentials/fixtures/template-credential-schema.json"; +import { useProviderWizardStore } from "@/store/provider-wizard/store"; +import type { ProviderSchemasResult } from "@/types/provider-schema"; + +const { getProviderSchemas, saveDynamicProviderCredentials, toast } = + vi.hoisted(() => ({ + getProviderSchemas: vi.fn(), + saveDynamicProviderCredentials: vi.fn(), + toast: vi.fn(), + })); +vi.mock("@/actions/providers/provider-schemas", () => ({ getProviderSchemas })); +vi.mock("@/actions/providers/dynamic-provider-credentials", () => ({ + saveDynamicProviderCredentials, +})); +vi.mock("@/components/shadcn/toast", () => ({ useToast: () => ({ toast }) })); + +import { DynamicCredentialsStep } from "./dynamic-credentials-step"; + +beforeAll(() => { + for (const method of [ + "hasPointerCapture", + "setPointerCapture", + "releasePointerCapture", + "scrollIntoView", + ]) { + Object.defineProperty(HTMLElement.prototype, method, { + configurable: true, + value: vi.fn(() => false), + }); + } +}); + +const props = { + providerId: "account", + providerType: "acme", + onNext: vi.fn(), + onBack: vi.fn(), + onFooterChange: vi.fn(), +}; +const schema = { + type: "object", + description: openaiSchema.description, + properties: { + token: { + type: "string", + title: "API token", + format: "password", + writeOnly: true, + }, + }, + required: ["token"], +}; + +describe("dynamic credentials in the provider wizard", () => { + beforeEach(() => { + vi.clearAllMocks(); + sessionStorage.clear(); + localStorage.clear(); + useProviderWizardStore.getState().reset(); + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "acme", + secretTypes: { api_key: schema }, + }); + saveDynamicProviderCredentials.mockResolvedValue({ + status: "saved", + secretId: "secret", + }); + }); + it("saves through the dynamic action and never persists entered secrets", async () => { + render(); + const field = await screen.findByLabelText(/API token/); + fireEvent.change(field, { target: { value: "only-in-memory" } }); + expect(JSON.stringify(sessionStorage)).not.toContain("only-in-memory"); + expect(JSON.stringify(localStorage)).not.toContain("only-in-memory"); + fireEvent.submit(field.closest("form")!); + await waitFor(() => expect(props.onNext).toHaveBeenCalledOnce()); + expect(saveDynamicProviderCredentials).toHaveBeenCalledWith({ + providerId: "account", + secretType: "api_key", + secret: { token: "only-in-memory" }, + }); + expect(useProviderWizardStore.getState().secretId).toBe("secret"); + expect(field).toHaveValue(""); + }); + it("masks the OpenAI API key and submits the original credential values", async () => { + // Given + const user = userEvent.setup(); + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "openai", + secretTypes: { api_key: openaiSchema }, + }); + render(); + const apiKey = await screen.findByLabelText(/Platform Api Key/); + const organization = screen.getByLabelText(/Organization Id/); + const baseUrl = screen.getByLabelText(/Base Url/); + + // When + await user.type(organization, "org-fixture"); + await user.type(apiKey, "fixture-key-not-a-secret"); + + // Then + expect(apiKey).toHaveAttribute("type", "password"); + expect(apiKey).toHaveAttribute("autocomplete", "new-password"); + expect(organization).toHaveAttribute("type", "text"); + expect(baseUrl).toHaveAttribute("type", "text"); + expect( + screen.queryByRole("button", { name: /show|reveal/i }), + ).not.toBeInTheDocument(); + + // When / Then: this form submits from the wizard's external footer. + act(() => apiKey.closest("form")!.requestSubmit()); + await waitFor(() => expect(props.onNext).toHaveBeenCalledOnce()); + expect(saveDynamicProviderCredentials).toHaveBeenCalledWith({ + providerId: "account", + secretType: "api_key", + secret: { + organization_id: "org-fixture", + platform_api_key: "fixture-key-not-a-secret", + base_url: "https://api.openai.com/v1", + }, + }); + }); + it("renders and submits the installed Template credential form with typed values", async () => { + // Given + const user = userEvent.setup(); + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "template", + secretTypes: { static: templateSchema }, + }); + render(); + const apiUrl = await screen.findByLabelText(/API URL/); + const apiKey = screen.getByLabelText(/API Key/); + const verifyTls = screen.getByRole("checkbox", { name: "Verify TLS" }); + const timeout = screen.getByRole("spinbutton", { name: "Timeout" }); + + // Then + expect(apiUrl).toHaveAttribute("placeholder", "https://api.acme.com"); + expect(apiKey).toHaveAttribute("type", "password"); + expect(screen.getByLabelText("CA Bundle").tagName).toBe("TEXTAREA"); + expect(verifyTls).toBeChecked(); + expect(timeout).toHaveValue(30); + expect(timeout).toHaveAttribute("min", "1"); + expect(timeout).toHaveAttribute("max", "300"); + expect(timeout).toHaveAttribute("step", "1"); + expect( + screen.getByRole("combobox", { name: "Authentication Scheme" }), + ).toHaveTextContent("bearer"); + expect(apiUrl).toHaveValue(""); + + // When: false must remain a boolean and numeric input must become a number. + await user.type(apiUrl, "https://api.example.test"); + await user.type(apiKey, "fixture-key-not-a-secret"); + await user.click(verifyTls); + await user.clear(timeout); + await user.type(timeout, "60"); + act(() => apiKey.closest("form")!.requestSubmit()); + + // Then + await waitFor(() => expect(props.onNext).toHaveBeenCalledOnce()); + expect(saveDynamicProviderCredentials).toHaveBeenCalledWith({ + providerId: "account", + secretType: "static", + secret: { + api_url: "https://api.example.test", + api_key: "fixture-key-not-a-secret", + verify_tls: false, + timeout_seconds: 60, + auth_scheme: "bearer", + }, + }); + }); + it.each<{ result: ProviderSchemasResult; title: string }>([ + { + result: { status: "success", providerType: "acme", secretTypes: {} }, + title: "Credential form unavailable", + }, + { + result: { + status: "success", + providerType: "acme", + secretTypes: { + api_key: { + type: "object", + properties: { nested: { type: "object" } }, + }, + }, + }, + title: "Credential form not supported", + }, + { + result: { status: "access_denied" }, + title: "Access required", + }, + { + result: { status: "unavailable" }, + title: "Provider installation unavailable", + }, + ])( + "explains $title without allowing credential submission", + async ({ result, title }) => { + getProviderSchemas.mockResolvedValue(result); + render(); + expect( + await screen.findByRole("button", { name: "Try again" }), + ).toBeVisible(); + expect(screen.getByRole("alert")).toHaveTextContent(title); + expect(screen.queryByLabelText(/API token/)).not.toBeInTheDocument(); + expect(saveDynamicProviderCredentials).not.toHaveBeenCalled(); + }, + ); + it("explains a loading failure and recovers when retried", async () => { + // Given + getProviderSchemas.mockRejectedValueOnce(new Error("Network unavailable")); + const user = userEvent.setup(); + render(); + expect(await screen.findByRole("alert")).toHaveTextContent( + "Could not load credential form", + ); + expect(screen.getByRole("alert")).toHaveTextContent( + "Check your connection and try again.", + ); + expect(screen.getByRole("link", { name: "Open Registry" })).toHaveAttribute( + "href", + "/registry", + ); + + // When + await user.click(screen.getByRole("button", { name: "Try again" })); + + // Then + expect(await screen.findByLabelText(/API token/)).toBeVisible(); + expect(screen.queryByRole("alert")).not.toBeInTheDocument(); + }); + it("clears credentials when changing providers", async () => { + const view = render(); + fireEvent.change(await screen.findByLabelText(/API token/), { + target: { value: "previous-secret" }, + }); + view.rerender( + , + ); + await waitFor(() => + expect(screen.getByLabelText(/API token/)).toHaveValue(""), + ); + }); + it("clears credentials when switching authentication methods", async () => { + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "acme", + secretTypes: { api_key: schema, personal_token: schema }, + }); + render(); + fireEvent.change(await screen.findByLabelText(/API token/), { + target: { value: "previous-method-secret" }, + }); + const user = userEvent.setup(); + await user.click( + screen.getByRole("combobox", { name: "Authentication method" }), + ); + await user.click(screen.getByRole("option", { name: "personal token" })); + expect(screen.getByLabelText(/API token/)).toHaveValue(""); + expect(JSON.stringify(sessionStorage)).not.toContain( + "previous-method-secret", + ); + expect(JSON.stringify(localStorage)).not.toContain( + "previous-method-secret", + ); + }); + it("rejects double submission and retries a failed save for the same account", async () => { + let rejectSave!: (error: Error) => void; + saveDynamicProviderCredentials.mockImplementationOnce( + () => + new Promise((_resolve, reject) => { + rejectSave = reject; + }), + ); + render(); + const field = await screen.findByLabelText(/API token/); + fireEvent.change(field, { target: { value: "retry-secret" } }); + fireEvent.submit(field.closest("form")!); + fireEvent.submit(field.closest("form")!); + expect(saveDynamicProviderCredentials).toHaveBeenCalledOnce(); + rejectSave(new Error("Network unavailable")); + await screen.findByText( + "Could not save the credentials. Check your connection and retry.", + ); + expect(props.onNext).not.toHaveBeenCalled(); + fireEvent.submit(field.closest("form")!); + await waitFor(() => expect(props.onNext).toHaveBeenCalledOnce()); + expect(saveDynamicProviderCredentials).toHaveBeenCalledTimes(2); + expect(saveDynamicProviderCredentials).toHaveBeenLastCalledWith({ + providerId: "account", + secretType: "api_key", + secret: { token: "retry-secret" }, + }); + }); + it("keeps other field and form errors visible while editing one credential", async () => { + // Given + const user = userEvent.setup(); + getProviderSchemas.mockResolvedValue({ + status: "success", + providerType: "acme", + secretTypes: { + api_key: { + ...schema, + properties: { + ...schema.properties, + project: { type: "string", title: "Project" }, + }, + required: ["token", "project"], + }, + }, + }); + saveDynamicProviderCredentials.mockResolvedValueOnce({ + status: "invalid", + errors: { + token: "Token was rejected", + project: "Project is unavailable", + _form: "Review the credential fields", + }, + }); + render(); + const token = await screen.findByLabelText(/API token/); + await user.type(token, "fixture-token"); + await user.type(screen.getByLabelText(/Project/), "fixture-project"); + act(() => token.closest("form")!.requestSubmit()); + expect(await screen.findByText("Token was rejected")).toBeVisible(); + + // When + await user.type(token, "-edited"); + + // Then + expect(screen.queryByText("Token was rejected")).not.toBeInTheDocument(); + expect(screen.getByText("Project is unavailable")).toBeVisible(); + expect(screen.getByText("Review the credential fields")).toBeVisible(); + + // When / Then: submitting again replaces the earlier validation errors. + act(() => token.closest("form")!.requestSubmit()); + await waitFor(() => expect(props.onNext).toHaveBeenCalledOnce()); + expect( + screen.queryByText("Project is unavailable"), + ).not.toBeInTheDocument(); + expect( + screen.queryByText("Review the credential fields"), + ).not.toBeInTheDocument(); + }); +}); diff --git a/ui/components/providers/wizard/steps/dynamic-credentials-step.tsx b/ui/components/providers/wizard/steps/dynamic-credentials-step.tsx new file mode 100644 index 0000000000..35fc5f0daa --- /dev/null +++ b/ui/components/providers/wizard/steps/dynamic-credentials-step.tsx @@ -0,0 +1,336 @@ +"use client"; + +import { RotateCcw } from "lucide-react"; +import Link from "next/link"; +import { useEffect, useRef, useState } from "react"; + +import { saveDynamicProviderCredentials } from "@/actions/providers/dynamic-provider-credentials"; +import { getProviderSchemas } from "@/actions/providers/provider-schemas"; +import { RegistryCredentialFields } from "@/components/providers/workflow/provider-credential-fields"; +import { Button } from "@/components/shadcn/button/button"; +import { Field, FieldLabel } from "@/components/shadcn/field/field"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/shadcn/select/select"; +import { Skeleton } from "@/components/shadcn/skeleton/skeleton"; +import { useToast } from "@/components/shadcn/toast"; +import { StatusAlert } from "@/components/shared/status-alert"; +import { + parseRegistryCredentialSchema, + type RegistryCredentialSchema, +} from "@/lib/provider-credentials/provider-credential-schema"; +import { + getCredentialDefaults, + validateCredentialValues, +} from "@/lib/provider-credentials/provider-credential-values"; +import { useProviderWizardStore } from "@/store/provider-wizard/store"; +import type { ProviderSchemasResult } from "@/types/provider-schema"; + +import { + WIZARD_FOOTER_ACTION_TYPE, + type WizardFooterConfig, +} from "./footer-controls"; + +interface DynamicCredentialsStepProps { + providerId: string; + providerType: string; + onNext: () => void; + onBack: () => void; + onFooterChange: (config: WizardFooterConfig) => void; +} + +function credentialFormError(status: ProviderSchemasResult["status"]) { + switch (status) { + case "access_denied": + return { + title: "Access required", + description: + "Your session may have expired or you may not have permission. Sign in again or contact your administrator.", + }; + case "unavailable": + return { + title: "Provider installation unavailable", + description: + "Install this provider's artifact again in Registry, then try again.", + }; + case "not_found": + return { + title: "Credential form unavailable", + description: + "This provider does not provide a credential form. Contact its publisher or your administrator.", + }; + case "success": + case "malformed": + return { + title: "Credential form not supported", + description: + "We could not display this provider's credential form. Contact its publisher or your administrator.", + }; + default: + return { + title: "Could not load credential form", + description: "Check your connection and try again.", + }; + } +} + +function DynamicCredentialForm({ + providerId, + secretType, + schema, + onNext, + onBack, + onFooterChange, + onLoadingChange, +}: Omit & { + secretType: string; + schema: RegistryCredentialSchema; + onLoadingChange: (value: boolean) => void; +}) { + const { toast } = useToast(); + const setSecretId = useProviderWizardStore((state) => state.setSecretId); + // Credentials belong only to this form. A new account or authentication + // method mounts a fresh instance; no values enter the persisted wizard store. + const [values, setValues] = useState(() => getCredentialDefaults(schema)); + const [errors, setErrors] = useState>({}); + const [saving, setSaving] = useState(false); + const inFlight = useRef(false); + const mounted = useRef(true); + const formId = "provider-wizard-dynamic-credentials-form"; + const valid = validateCredentialValues(schema, values).valid; + useEffect(() => { + mounted.current = true; + return () => { + mounted.current = false; + }; + }, []); + + useEffect(() => { + onFooterChange({ + showBack: true, + backLabel: "Back", + backDisabled: saving, + onBack, + showAction: true, + actionLabel: "Authenticate", + actionDisabled: saving || !valid, + actionType: WIZARD_FOOTER_ACTION_TYPE.SUBMIT, + actionFormId: formId, + }); + }, [onBack, onFooterChange, saving, valid]); + + return ( +
    { + event.preventDefault(); + if (inFlight.current) return; + const validation = validateCredentialValues(schema, values); + setErrors(validation.errors); + if (!validation.valid) return; + inFlight.current = true; + setSaving(true); + onLoadingChange(true); + try { + const result = await saveDynamicProviderCredentials({ + providerId, + secretType, + secret: validation.secret, + }); + if (!mounted.current) return; + if (result.status === "saved") { + setValues({}); + setSecretId(result.secretId); + toast({ + title: "Credentials saved", + description: "Test the provider connection to continue.", + }); + onNext(); + } else if (result.status === "invalid") { + setErrors(result.errors); + } else { + const description = + result.status === "schema_unavailable" + ? "The credential schema is unavailable. Check the installed artifact in Registry and reload the form." + : result.status === "access_denied" + ? "You no longer have permission to update these credentials. Contact an administrator." + : "Check your credentials and try again. Your provider account is already created."; + setErrors({ _form: description }); + toast({ + variant: "destructive", + title: "Credentials could not be saved", + description, + }); + } + } catch { + if (mounted.current) { + const description = + "Could not save the credentials. Check your connection and retry."; + setErrors({ _form: description }); + toast({ + variant: "destructive", + title: "Credentials could not be saved", + description, + }); + } + } finally { + inFlight.current = false; + if (mounted.current) { + setSaving(false); + onLoadingChange(false); + } + } + }} + > +
    + {errors._form && ( + + {errors._form} + + )} + { + setValues((current) => ({ ...current, [name]: value })); + setErrors((current) => { + const next = { ...current }; + delete next[name]; + return next; + }); + }} + /> +
    +
    + ); +} + +function DynamicCredentialsContent(props: DynamicCredentialsStepProps) { + const { providerType, onBack, onFooterChange } = props; + const [schemas, setSchemas] = useState(null); + const [selectedMethod, setSelectedMethod] = useState(""); + const [attempt, setAttempt] = useState(0); + const [saving, setSaving] = useState(false); + useEffect(() => { + let active = true; + setSchemas(null); + setSelectedMethod(""); + getProviderSchemas(providerType) + .then((result) => { + if (active) setSchemas(result); + }) + .catch(() => { + if (active) setSchemas({ status: "error" }); + }); + return () => { + active = false; + }; + }, [providerType, attempt]); + + const methods = + schemas?.status === "success" ? Object.keys(schemas.secretTypes) : []; + const secretType = selectedMethod || methods[0]; + const schema = + schemas?.status === "success" && secretType + ? parseRegistryCredentialSchema(schemas.secretTypes[secretType]) + : null; + useEffect(() => { + if (!schema) + onFooterChange({ + showBack: true, + backLabel: "Back", + onBack, + showAction: false, + actionLabel: "Authenticate", + actionType: WIZARD_FOOTER_ACTION_TYPE.BUTTON, + }); + }, [schema, onBack, onFooterChange]); + + if (!schemas) + return ( +
    + + +
    + ); + + const error = credentialFormError( + schemas.status === "success" && methods.length === 0 + ? "not_found" + : schemas.status, + ); + + return ( +
    + {methods.length > 1 && ( + + + Authentication method + + + + )} + {schema ? ( + + ) : ( +
    + + {error.description} + +
    + + +
    +
    + )} +
    + ); +} + +export function DynamicCredentialsStep(props: DynamicCredentialsStepProps) { + return ( + + ); +} diff --git a/ui/components/providers/wizard/steps/footer-controls.ts b/ui/components/providers/wizard/steps/footer-controls.ts index ff41ae8061..7bdd0d5d58 100644 --- a/ui/components/providers/wizard/steps/footer-controls.ts +++ b/ui/components/providers/wizard/steps/footer-controls.ts @@ -22,6 +22,7 @@ export interface WizardFooterConfig { onSecondaryAction?: () => void; showAction: boolean; actionLabel: string; + actionLoading?: boolean; actionDisabled?: boolean; actionType: WizardFooterActionType; actionFormId?: string; diff --git a/ui/components/providers/workflow/forms/connect-account-form.test.tsx b/ui/components/providers/workflow/forms/connect-account-form.test.tsx new file mode 100644 index 0000000000..7e74064f8e --- /dev/null +++ b/ui/components/providers/workflow/forms/connect-account-form.test.tsx @@ -0,0 +1,84 @@ +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; + +const { addProvider, updateProvider, getInstalledRegistryProviderOptions } = + vi.hoisted(() => ({ + addProvider: vi.fn(), + updateProvider: vi.fn(), + getInstalledRegistryProviderOptions: vi.fn(), + })); + +vi.mock("next/navigation", () => ({ + useRouter: () => ({ push: vi.fn() }), +})); +vi.mock("@/actions/providers/providers", () => ({ + addProvider, + updateProvider, +})); +vi.mock("@/actions/providers/registry-provider", () => ({ + addRegistryProvider: vi.fn(), +})); +vi.mock("@/actions/registry/registry", () => ({ + getInstalledRegistryProviderOptions, +})); + +import { ConnectAccountForm } from "./connect-account-form"; + +describe("provider account aliases", () => { + beforeEach(() => { + vi.clearAllMocks(); + getInstalledRegistryProviderOptions.mockResolvedValue({ + status: "access_denied", + }); + }); + + it("saves an alias changed after an account was already created", async () => { + // Given + const onSuccess = vi.fn(); + const user = userEvent.setup(); + const account = { + id: "existing", + attributes: { provider: "github", uid: "octocat", alias: "Original" }, + }; + addProvider.mockResolvedValue({ data: account }); + updateProvider.mockResolvedValue({ + data: { + ...account, + attributes: { ...account.attributes, alias: "Edited" }, + }, + }); + render(); + await user.click(screen.getByRole("option", { name: "GitHub" })); + await user.type( + screen.getByRole("textbox", { name: "Username/Organization" }), + "octocat", + ); + const alias = screen.getByRole("textbox", { + name: "Provider alias (optional)", + }); + await user.type(alias, "Original"); + await user.click(screen.getByRole("button", { name: "Next" })); + await waitFor(() => expect(onSuccess).toHaveBeenCalledOnce()); + + // When + await user.clear(alias); + await user.type(alias, "Edited"); + await user.click(screen.getByRole("button", { name: "Next" })); + + // Then + await waitFor(() => + expect(onSuccess).toHaveBeenLastCalledWith({ + id: "existing", + providerType: "github", + uid: "octocat", + alias: "Edited", + }), + ); + expect(addProvider).toHaveBeenCalledOnce(); + expect(Object.fromEntries(updateProvider.mock.calls[0][0])).toMatchObject({ + providerId: "existing", + providerAlias: "Edited", + }); + }); +}); diff --git a/ui/components/providers/workflow/forms/connect-account-form.tsx b/ui/components/providers/workflow/forms/connect-account-form.tsx index a46de4871d..2ccd6531ff 100644 --- a/ui/components/providers/workflow/forms/connect-account-form.tsx +++ b/ui/components/providers/workflow/forms/connect-account-form.tsx @@ -3,20 +3,25 @@ import { zodResolver } from "@hookform/resolvers/zod"; import { ChevronLeftIcon, ChevronRightIcon, Loader2 } from "lucide-react"; import { useRouter } from "next/navigation"; -import { Dispatch, SetStateAction, useEffect, useState } from "react"; +import { Dispatch, SetStateAction, useEffect, useRef, useState } from "react"; import { useForm, UseFormReturn } from "react-hook-form"; -import { z } from "zod"; -import { addProvider } from "@/actions/providers/providers"; +import { addProvider, updateProvider } from "@/actions/providers/providers"; +import { addRegistryProvider } from "@/actions/providers/registry-provider"; +import { getInstalledRegistryProviderOptions } from "@/actions/registry/registry"; import { AwsMethodSelector } from "@/components/providers/organizations/aws-method-selector"; import { AzureMethodSelector } from "@/components/providers/organizations/azure-method-selector"; import { GcpMethodSelector } from "@/components/providers/organizations/gcp-method-selector"; import { WizardInputField } from "@/components/providers/workflow/forms/fields"; import { ProviderTitleDocs } from "@/components/providers/workflow/provider-title-docs"; import { Button, useToast } from "@/components/shadcn"; +import { Alert, AlertDescription, AlertTitle } from "@/components/shadcn/alert"; import { Form } from "@/components/shadcn/form"; +import { ProviderCredentialFields } from "@/lib/provider-credentials/provider-credential-fields"; +import type { RegistryProviderOption } from "@/lib/registry/provider-options"; import { - addProviderFormSchema, + createAddProviderFormSchema, + AddProviderFormValues, ApiError, KnownProviderType, ProviderType, @@ -26,10 +31,11 @@ import { OrgFlowType, toOrgFlowType, } from "@/types/organizations"; +import { isKnownProviderType } from "@/types/providers"; import { RadioGroupProvider } from "../../radio-group-provider"; -export type FormValues = z.infer; +export type FormValues = AddProviderFormValues; export interface ConnectAccountSuccessData { id: string; @@ -209,7 +215,41 @@ export const ConnectAccountForm = ({ const [method, setMethod] = useState<"single" | null>(null); const router = useRouter(); - const formSchema = addProviderFormSchema; + const [registryOptions, setRegistryOptions] = useState< + RegistryProviderOption[] + >([]); + const [registryError, setRegistryError] = useState(false); + const [providerError, setProviderError] = useState(null); + const [discoveryAttempt, setDiscoveryAttempt] = useState(0); + const submitting = useRef(false); + const createdAccount = useRef(null); + + useEffect(() => { + let active = true; + const load = async () => { + try { + const result = await getInstalledRegistryProviderOptions(); + if (!active) return; + setRegistryOptions(result.status === "ready" ? result.options : []); + setRegistryError(result.status === "error"); + } catch { + if (active) { + setRegistryOptions([]); + setRegistryError(true); + } + } + }; + void load(); + window.addEventListener("registry-artifacts-changed", load); + return () => { + active = false; + window.removeEventListener("registry-artifacts-changed", load); + }; + }, [discoveryAttempt]); + + const formSchema = createAddProviderFormSchema( + registryOptions.map((option) => option.type), + ); const form = useForm({ resolver: zodResolver(formSchema), @@ -229,6 +269,22 @@ export const ConnectAccountForm = ({ const isLoading = form.formState.isSubmitting; const onSubmitClient = async (values: FormValues) => { + if (submitting.current) return; + const existingAccount = + createdAccount.current?.providerType === values.providerType && + createdAccount.current.uid === values.providerUid + ? createdAccount.current + : null; + if ( + existingAccount && + (existingAccount.alias ?? "") === (values.providerAlias?.trim() ?? "") && + onSuccess + ) { + onSuccess(existingAccount); + return; + } + submitting.current = true; + setProviderError(null); const formValues = { ...values }; const formData = new FormData(); @@ -237,7 +293,20 @@ export const ConnectAccountForm = ({ ); try { - const data = await addProvider(formData); + let data; + if (existingAccount) { + const update = new FormData(); + update.set(ProviderCredentialFields.PROVIDER_ID, existingAccount.id); + update.set( + ProviderCredentialFields.PROVIDER_ALIAS, + values.providerAlias?.trim() ?? "", + ); + data = await updateProvider(update); + } else { + data = await (isKnownProviderType(values.providerType) + ? addProvider(formData) + : addRegistryProvider(formData)); + } if (data?.errors && data.errors.length > 0) { data.errors.forEach((error: ApiError) => { @@ -246,10 +315,9 @@ export const ConnectAccountForm = ({ switch (pointer) { case "/data/attributes/provider": - form.setError("providerType", { - type: "server", - message: errorMessage, - }); + // Provider selection is hidden here; keep failures visible and + // retryable when availability changes without editing the form. + setProviderError(errorMessage); break; case "/data/attributes/uid": case "/data/attributes/__all__": @@ -280,12 +348,13 @@ export const ConnectAccountForm = ({ } = data.data; if (onSuccess) { - onSuccess({ + createdAccount.current = { id, providerType: createdProviderType, uid: uid || values.providerUid, alias: alias ?? values.providerAlias ?? null, - }); + }; + onSuccess(createdAccount.current); return; } @@ -301,10 +370,13 @@ export const ConnectAccountForm = ({ ? error.message : "Something went wrong. Please try again.", }); + } finally { + submitting.current = false; } }; const handleBackStep = () => { + setProviderError(null); applyBackStep({ prevStep, method, @@ -327,6 +399,7 @@ export const ConnectAccountForm = ({ useEffect(() => { onBackHandlerChange?.(() => { + setProviderError(null); applyBackStep({ prevStep, method, @@ -352,7 +425,7 @@ export const ConnectAccountForm = ({ onUiStateChange?.({ showBack: prevStep === 2, showAction: prevStep === 2 && showUidForm, - actionLabel: "Next", + actionLabel: isLoading ? "Creating provider..." : "Next", actionDisabled: !canSubmit || isLoading, isLoading, }); @@ -375,7 +448,26 @@ export const ConnectAccountForm = ({ {/* Step 1: Provider selection */} {prevStep === 1 && (
    + {registryError && ( + + Registry providers could not be loaded + + Built-in providers are available. Check the Registry + connection and try again. + + + + )} + {providerError && ( + + Unable to create provider + {providerError} + + )} {isLoading ? ( - + ) : ( )} - {isLoading ? "Loading" : "Next"} + {isLoading ? "Creating provider..." : "Next"} )}
    diff --git a/ui/components/providers/workflow/provider-credential-fields.test.tsx b/ui/components/providers/workflow/provider-credential-fields.test.tsx new file mode 100644 index 0000000000..6925925f23 --- /dev/null +++ b/ui/components/providers/workflow/provider-credential-fields.test.tsx @@ -0,0 +1,136 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeAll, describe, expect, it, vi } from "vitest"; + +import type { RegistryCredentialSchema } from "@/lib/provider-credentials/provider-credential-schema"; + +import { RegistryCredentialFields } from "./provider-credential-fields"; + +const schema: RegistryCredentialSchema = { + fields: [ + { + name: "api_key", + label: "API Key", + description: "Issued from the console.", + kind: "password", + required: true, + }, + { + name: "scheme", + label: "Scheme", + kind: "select", + options: ["bearer", "basic"], + required: false, + }, + { name: "notes", label: "Notes", kind: "textarea", required: false }, + ], +}; + +beforeAll(() => { + for (const name of [ + "hasPointerCapture", + "releasePointerCapture", + "scrollIntoView", + ]) { + Object.defineProperty(HTMLElement.prototype, name, { + configurable: true, + value: () => false, + }); + } +}); + +describe("RegistryCredentialFields", () => { + it("renders accessible controlled credential fields and emits changes", async () => { + // Given + const user = userEvent.setup(); + const onChange = vi.fn(); + + render( + , + ); + + // When + await user.type(screen.getByLabelText(/API Key/), "x"); + await user.click(screen.getByRole("combobox", { name: "Scheme" })); + await user.keyboard("{ArrowDown}{Enter}"); + + // Then + const apiKey = screen.getByLabelText(/API Key/); + const description = screen.getByText("Issued from the console."); + const error = screen.getByRole("alert"); + expect(apiKey).toHaveAttribute("type", "password"); + expect(apiKey).toHaveAttribute("autocomplete", "new-password"); + + expect(apiKey).toHaveAttribute( + "aria-describedby", + `${description.id} ${error.id}`, + ); + expect(apiKey.id).toMatch(/-0-control$/); + expect(apiKey).toHaveAttribute("aria-invalid", "true"); + expect(apiKey).toBeRequired(); + expect(description.id).toMatch(/-0-description$/); + expect(error).toHaveTextContent("A key is required."); + expect(error.id).toMatch(/-0-error$/); + expect(onChange).toHaveBeenCalledWith("api_key", "x"); + expect(onChange).toHaveBeenCalledWith("scheme", "basic"); + }); + + it("uses unique index-based IDs for hostile field names and instances", () => { + // Given + + const hostileSchema: RegistryCredentialSchema = { + fields: [ + { + name: "x-description", + label: "First", + kind: "text", + required: false, + }, + { + name: "registry-credential-x", + label: "Second", + description: "Second description.", + kind: "text", + required: false, + }, + ], + }; + + const { container } = render( + <> + + + + , + ); + + // When / Then + expect(screen.getByLabelText("First").id).toMatch(/-0-control$/); + + expect(screen.getByText("Second description.").id).toMatch( + /-1-description$/, + ); + const ids = Array.from(container.querySelectorAll("[id]"), ({ id }) => id); + expect(new Set(ids).size).toBe(ids.length); + }); +}); diff --git a/ui/components/providers/workflow/provider-credential-fields.tsx b/ui/components/providers/workflow/provider-credential-fields.tsx new file mode 100644 index 0000000000..157f4a0d7e --- /dev/null +++ b/ui/components/providers/workflow/provider-credential-fields.tsx @@ -0,0 +1,152 @@ +"use client"; + +import { type ChangeEvent, useId } from "react"; + +import { Checkbox } from "@/components/shadcn/checkbox/checkbox"; +import { Field, FieldError, FieldLabel } from "@/components/shadcn/field/field"; +import { Input } from "@/components/shadcn/input/input"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/shadcn/select/select"; +import { Textarea } from "@/components/shadcn/textarea/textarea"; +import type { + RegistryCredentialSchema, + RegistryCredentialValue, +} from "@/lib/provider-credentials/provider-credential-schema"; + +interface RegistryCredentialFieldsProps { + readonly errors: Readonly>; + readonly onChange: (name: string, value: RegistryCredentialValue) => void; + readonly schema: RegistryCredentialSchema; + readonly values: Readonly< + Record + >; +} + +export function RegistryCredentialFields({ + errors, + onChange, + schema, + values, +}: RegistryCredentialFieldsProps) { + const instanceId = useId(); + + return ( +
    + {schema.fields.map((field, index) => { + const error = errors[field.name]; + const fieldId = `registry-credential-${instanceId}-${index}`; + const id = `${fieldId}-control`; + const descriptionId = field.description + ? `${fieldId}-description` + : undefined; + const errorId = error ? `${fieldId}-error` : undefined; + const describedBy = + [descriptionId, errorId].filter(Boolean).join(" ") || undefined; + const invalid = error ? true : undefined; + const value = values[field.name]; + const textControlProps = { + "aria-describedby": describedBy, + "aria-invalid": invalid, + id, + + onChange: ( + event: ChangeEvent, + ) => onChange(field.name, event.target.value), + required: field.required, + placeholder: field.placeholder, + spellCheck: false, + value: + typeof value === "string" || typeof value === "number" ? value : "", + }; + + return ( + + {field.kind === "checkbox" ? ( +
    + + onChange(field.name, checked === true) + } + /> + + {field.label} + {field.required && } + +
    + ) : ( + + {field.label} + {field.required && } + + )} + {field.kind === "checkbox" ? null : field.kind === "select" ? ( + + ) : field.kind === "textarea" ? ( +

aAUurC{Amb0laa!Kb^8)!R)2til9| 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 NC#@uvETMnrzW|0m_l5uf literal 123059 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%0Ah!9V&{GV|fw(2&fZiKbD%+;^Jna`h}U0EK? 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 TZl`+ZUrvI8ihRP+b2t7A>*;aM diff --git a/docs/images/prowler-app/slack/connected-workspace.png b/docs/images/prowler-app/slack/connected-workspace.png index ec99ccb880fa0a5c3652b9dc46588a701b99fa3c..ae3437d84ef4f2e5cd3cbd2d3cc446719e11ff07 100644 GIT binary patch literal 113939 zcmY(qbzD^I_dSksMI}V(5KxgWX=!PsyGuHxOKL_%KtPa&p$C{D2b69^MPR6*B}YJV zfPrD?`kni^*Zcnd<}Y5uIcJ{O&)RFRy-tj-wkjDh12F*s0oijkC4B;do39B7{(5@r zI`ED2XJaY?g1ZFImE;XyK z@21wqCU>Z*MiOzrQ5(31t+>y##dUP_EB34p45CPKTsoqW8={C=UpR4(MO(ehK97FfqIY}DHHc3#dHoQS?65j} z@6WxzRN2W3zBPjUszC`n!m|D^)W@&buL{Ni}#1W;RB-+fD1S=N}4$R%^aRjqu8w1$>_O>IiVoG4oR>Z0qN%ZI5V^95?C^_%b%5~*ng9_#( z`HGB9iHOOIkOvX}UDKQh4<{-NOBtxN69~R`(2fOsiJ?zP`VFE{yrg{nw*Y_4Eqbqg%>ngC8=8sz7-Vgt~%Yh6> zAh|!bX6P>H40`{b)EvgE;fRV=V45Vo_U9sCX&>y5t{Fo8BoC(q98lbjX2KDZ(7S*B zPtYOGT2B#EB~kg4aV*C3Ns(G+YKf-y_KmJAO(m@=R<7Y4{RNeYY+bD7qw11Lb}&|7 zFp}cLC)PcsME8-N+ylNqTG>}Wl$a?fg?;~fXksv_zT6-lZ5l`8TJ{4A__H@}V?p6z3v!`{TdRW~ zHcfKBi$q79=eO{U@q!q<(sK*AsjawW@xOu7GY?ioo`ndSxSO{^h3mCT;SC42Smd z^1(V0=e|d9KG$+)%tU#&2M>!iGU^9u$ma3wO%M21s1+!oOi_p7TSz@-w?V>r@%n*6 zIj{5<+Oj=xaC@fSP`T_ZSIjjT)nUUE+dI=e(YCo7I5B9|&JI?+eoch()+fliLK3~m zb(cSrM|Ib^g7yA7$F9bQ24aaxNG5d0CMT;xKjsk<-GM)Sb+`r5B)=>%OIZd){? z%x*=FgrDLWCH>d)WJ3M1CWJAr+NvV~!N?&d*{lSA)AziE?ZJv{QhAb|U&lW$o3#v> zwPdgd_a+$p>-tOf7F|uEc!K|MW3vXDUCgwPp`n2EanE0^bhM7B#XiS>5oDy@U zta+NFKP~6Ic^vad<@swR|Lt*6%*2SrT>i=C6hg`a`Fq0vj%(+^+`)!)n7}jCn{?Ok^(yUWAlg)NlLU{8((C zEDD?W40=;O=;kM^LN=Cf_r*-?dJB99x{JO|-XA|m^D zNRWXBC$q!a!lvel=CqS6yFTO=l#Jm%0iW#0WT!#od>p#43z|m#>K{yARiYzwY z!}I!q(j;C3UAn@|^o-j%7-PK!LBZt$9-xlzDI>F~<^d)8%z7EM7RVn_MpMPe5`dnxKLSHLf zU_n7pJ&k*!J@jKY3GEXZvpVl zACiRxAw&A%3u}oCFGH4F!W6Todt9NGXLHaZEvY)KR&KHkL(t>pda2iCly%a!moJUK z7VD=wj#ryB%D0D@%*`EJpG)dzsn>B0;QdM}A#YbJOsctQ^@+4%_NgVRlmr?7Tlsax zyw6Nz#Y7ZNE??G5-dqz-Ra=pBoUOsp_D|{7-?aKs^8qT2(Qa1qV+!}FvUmg1pB(To zpwOD_*!ie$9hgC#&NKqq82<7m;%dH4ucGyin~IiR1mVp)4C2~jq6|-LQKtu(V60^C z;OpNFTtWJe^|JH~#vh1Ef!Y=p7-zz|p@QM7xV+z+)>xW}fci@jdOA8%dYl|1qs2kShxm9P!8}v+@baqWEcRe%e0zgLXd9B5iR!4T zsv`Yob01`XsxVvltm24afZ-B0a=`vm*NZ}_7$z!qOJ$W+js(O)Z1?mctW?POBydOC z3)Mm)d-1>o{TT82n{%g(bLGXciAs9%*h=D6cz)_r1JssbV^}%fEFq6*0bJIx+_N8) zdHC|>%a#C4hw~9X++^Ig(Nm_>hkefLXh){O3tfJh%ukZ18!=uP1*&KBB&ySWS>l+b zI$bwA$hf(3;5LyZsq*Abl}T+nN<&Mke$68uj zXn;E@FMQOC+Ze_*x0&mJwcA_Gp>Q5?=dQOEJ39*1lNAQeGx=a#he+r`n7C)pIAuI$ zqC(08=g>ujnY4e&AM|W9B|RVu$16f^zJ2SU;!O@N;}y8C3_S83Hf*VlIC1Ax*JF`M zz9=kyEGZ#jR+?2-w$Yo!TJ|-WO~aH3NGqn%cbFDB!JR=^>yVjTknq8}&%x$IqZhj7 zgJG#|(kQH7S?OIxD*64VyV%aFhEJb<uN#3{&F-%a`$gU)XK|gW@(G*xuY!54URZk0B`lQl+W{HsU6^DUn|Q-`e7y(u%n6{_3E($INdGMhc)TO-)Sz zW6^)W%*-t7zpndlEwJnNsobpaS7zS5%Puxmvhc>R*)wgPa4##KPOmqLgR$t*du5|K zKadFw7_=7Vw#CxzixqK`%zJTOoJt)>&Nd|q`@|sJVPEVOPQ1d?ru>Oa{O)19R5&ZO z(Dp>R5r)P_z0Va5RdjH8*W9e!qn%52O(fdxxVX4DozFrWA}K1#y@~BKDc{l<)L&MR z_a4luud-UsS1x}MC=qF5Qf)mUeGKeHRW*Smg6%0jL)N{DtH0ocU9}`Td)H`6Gf!4v zRYEDaD~Byk1nsUjfMmAAnwFNzS+A{>2UrFx6uJ|lYg|PSFcVr8JoD-EcO?%=O%ozC z@|zEGH^j?uk6jkn@|v^i;*7zRNpj%J;e0upChs?a#c0~g%S+5uwYZQFGKGVj?UQDQ z+6|+1bf=uh8Zr%&55C;P;c)x=v!Cs6%B(PaZfr!ihX&c&{`wY8j+sPg9F*Nj3)&cs zY~bp&{%ohLq@)x{ObtMVakaHpwTiOxe0yjkK)4MN_B{!z3BAUlUgM?rCIs{fzt1)M zl@$YFXL$zj^65q|7N*(do{zMA<_>Od<%_+|Rx^!W;Il)IP5kz3V}ClI!GNQ&{5Aak znvM}M_+*9lH28RT5vGwbIuf{!dV%}hH(swU$^c1XRh11r1=u@fTE|QuM0hQV zjIs2|)2GMlBSroy+-D4ojQJ9NQ3>G9@v=V{iuqh_G+N~}eSEBYTUgYO94LPO(Ejd^Eq?xqt@Q9fz=Th2vbqnS=O-nlCM9=d42d26 z3Om;ZNrau4>#Tj;>3qQRUl3or5N%!U+#)>?Zokh5q!R3Jp-^aTtzTH!`RZUcmmW+r zxHs`3i)>iIIleE2W1_;OL=xCKGGgLF(hN|S5yCtzq$I07fK3N*tKf8t-0WSBeZl|Eb z&fea`!^2gTUzFdh=CNaaLPEmP&U_In`22Y91_{m9BqAG?Wbn!gVJ_+hNr=7!x9g5A zQvC==_X06#A`xU@P;1w1DfZG7rmtNh;WUs5)O=CV(Ja!hb^%ld0MUe{G z_IPdRg@_#Z>|1v1bmQtzdi)U=i=_{R;ku8HSBrxB8@b&k&%78{hAfR0^y<+F|Dok^ z-oY>kiM}b(dtKt(<}#G|b|K>Ygrw~#c=(JWa!5r*#nWWIt-Y<>sCuF4dCFLccG)@X*d&pO>!x9S78)cKqpBO0{r7HyXijKkD3$rg#!g2G`EN zp#vUDRz^=!jEn|lURJWH=MU#gm*MW3A3^eGdbP5JnnCj|n#CU=dpRRb!+ebmcN!~& z#W9e$V$pNimGYQoYN$}Gf9TPURg?D%epiq2QaxMS2W-Wf9k1?s+?NWh3_m-hD%XFj zc@v1>3s%(xATKUX*?{?sE9qdvdU|?}{pqmc10XvZyUzXi0XHnuPh}cAvH}PlGq5p( zS)ygF^Q}Q+0$MW}zCQ!E9l*ri8>4KSagVH4=6e#DG&c4DhF=;)Ty$}9!PN|}icH7> z`8J;b`GAO=Su+}d2J``DsvKy+Ie0Aw#QI{Id$9)PXO^K6FpoioY9uZJq}&DIF>Ii~AI{qB?6XuR`6 zD#YA=BTHvc{K(8(&#p0Bd^BgPQv2f=P+=0`709R`Lzur$R#-Gzt0QyVP@7<$wXRMP zRk6&y0iC`1T-+%mvf3AH`!#ZCu43b?N;kDqCrKre`*AW7eOthmokEpkCjypcx2sl*AXRA`rj-?-MD+$L-H@f z4mOPta4{awBv_E~4aYtqEYmHCB~+TP9)LUsd2UHC` zYDTAKavAUJc|kVF8IkT}cUQ`zMy$5D)7Q_hKe0(-OxOjP+AJ#m4)l$?`k=Du=)od! zFm24_gNG009Tjua(x@+rbr1S81nTzC;48stwC*cEgNWu&M!|~md!eZB-``zd2TqGV zvsRg)haY9SXl-3xasFHub1Yev?s{)~Tbreo6^CXfs?w~s!#7*pi&?}aQN15Xoig6G zjUgWa{vs?Y+8%^mxG#Y$0I+$!+NSgB0t-e?aH?J|f0Vm^{rWmOk}B9h0C}_Wse8a2 zZFj1Vd%d~%KS$(C5Zj3uVHQZ8O~TDk%=Sm!!z-+1Uq*IgUX|%0SR+5k(O$iFuj#S5 zqE`8rjvuU=XrM;+F1J`1wi=`8yC(}uk_8#x$N|pJM$KQUrly&Q+}zX0>&A##Z$^*V z@K%`RnA2balMK?M(Pc6+Sb_$+Ehl6*O?JC~z@S8@a#f1hx6^N}jWl>zKm(C!JgOVQH(G%uXMSQ! zAZ~BYomTE&{1%fTWpm2>F2Dp8mftc{+{@bYVG_V%xp#DWKiAd<`TBxR zMis+@7-UY_BN7rr8K@px6e%XX_H+5^dY6KdQX`#r8hExw20zzOq?DNF2^D*%%1v_S zO3UUNI~(Gjh=>S_Mo&a<<-f{B4O!XN!!$WMaT7h{b;rfZBoRcx_H@v!Eh>SAR0U&i&?H`D&!kht?2pVJ(o zY5y5)V`T(`;8=c|BhJue&&h8?m?Hu%?YtCVFsGMzB%qZ_8)Ra=lWXxfYlARc`~bJ2 zL2L@3P;=n+48Wa^Pfstg;H#p{pTomm`1O%HckWPe0`l>PrJ0a}O_}i1@v$*s@a4Gz z*{HSV zDS0mgWW{HNhSUA<=%_@I0mymJo)L&2&o%1~Zj6;QzMM|>buJfvwfpP%_!!_K-Ui)V zLx;P&1tlWofUwo}YHtb9nE#}pNp?L=%~Z7oKJ=z(k?#=0gyUHLieF)VwW+IA73gwP z>!pfhumJkRC9)KfV7};?#8%fv)Se2xCQ{P$-ofnXIchjhhR>j3D}|%X$zpbTTJM>X z#J7vkqb3UV_(!a)S&c3)_6~->O8`V@eFkxs%4I;#B3VokrCU4R4N(OW~+k{#^+YIu`HRK)ntPnsFHT*{V|r)`peCUikwYZ;y85jbiL;qJZ6DfLQh)D$0LK^>YaH}almAyS$cZ9MZ?RD=~@oh zw=GQNB2e3mVSCosU66iU7n3pMW93_O>pGWv%8LN7 zVkZ%dk!`V&nbhhT{72^!SJ*kA<``RS58jUgMK`#PMGd8XT?c4nxgn#do1vQ8Ewb*f zktAH=COIVWgkNrLGJ>Bw}Qu#Wka zkJ(mHmRLztyL%^(Rp`yRmX$`l>G~i?UjNh?CY0Xg2LFYwfQ~T11XJTN5nI0JnObo!Q;mvey?$`w}iH#F=y+^*!~YwBDCVYjtJc~S*R zl4U8~(pyt#ssYR&FJpa$7JZni1e5r?&>X@m*=6hi0i3rUUFWZG)CIx$Hm2U%1fql(_B_cP@klvr2c5RsYLJGT#mx;FJGQ1-vAm(0Lhnm zwfnjcR5I=p6a)s27f@)vvJe&&gc4nxpO32!piqfI)4zV%E--CxZ?m$pidO0)-gdkW z2n@W$t&m{(d5mA0wufwFi&u-(*}jmsd1UVEZtcGQ=)r?$7eSIKp3NSQKS; zfBRM&GNJzB1ymFK(qr2b9j*(=7Q4INfKmn#f{kaqS+(QrzVC-v%?6I4Oz5EkAhVoG z5}NC5)H-<FSts1$iz^`t@hTkc8?`;UD zfZ29|M#_TKz#!k;e05vsk+B~Mpmb#|+gFh+;30iCi8qA*iSl!`ChGjibdJFSyxEN) zEYD8$m*!BH&)BY(*D1)T4qe^9+a0Y(>wWlGhI4GE41>OHi0g3PJOIiD;24Xmcddg( z4W)qkWV0cxal1g6E!+u5{p7m?3KuCfstvS>wP;f0D?~~c>6E&W6n*2LXXdqaBP2BH zECz#z?6x;6?xx5On|=B+KBRs4soqH1X*hpaN$H!`cSn@X*jj3Ye)R)c!l6u3Ntx7) zSF2*{aqK%{5y*+A>N6q9*OMQvuh8(B-m{_-m zh!XxYo!2a}N*>Fh6fKM|R^RXL?fZcNJ-BU$M|MACZ>c*^rj`Sp#4~fz`MVwD4rYnDsEWdNp zs|@qJN`hO>+zx~~Y-aBHze;7T5SWx-p^`ChX9&!%bx1m%kQkM_Fne@dLRo(7re0_I zTj6VGag9pt+MpcRe2jQ~j9sS#=zEG9X%G4p%*n@YSceUM_?fHdBOKWe?(<=@L=Hp_ z#UAi*hEHOxZvJW7jGyq%YLTZqh8;_v zBDDeJ6yOh*=#C2@@gV&bsHqxK4bayC+e<46nrHbJk^&u#za=t+8!ar z(n+{B?l${e*A#ZwS82D^C4$w{!LB2?^9_TqqSKMW&cDSU`qO%Rvca_`uAE z5f>2wSQ0C5`%Hs}_=~TP5vSD8?XskzM}-%-3uCDqYpA(@>^iqDx9&zCM_dF z_h%Nb#ejmn!?C|1jVB%M#q9qvubne|2i=Lym1?Y?Nx}q;6yDg#zB%9MC8wT0Hd0MT zgchqeJu(xgZ`c~hag1~9_qmnAw|6djKfl(p73e}8Rc&t$hcsWhpe1FiBkt$3vq$DX(kWYON)#H&#!#ClNi#Z2hmW&pF?5 zkMY;ppPo{Gd+n-K(k)(hTXQT00f)%zFy#u#TUZ--(Tl)_{nFj;ak{r3N2MQepAU6d zw@mM^x(*d!rVycvTl9G{q9T9$kpAzJXw)8dQW(4smzVEa6R@V2-1;bD?^6D3qSV(` z_X#k9TKpm4E*Sgt=@X;4XFQ!C_aI#sx2|ZpW-BUTV@F(Th6rUQ37|#IR^WbA6fu&% zZZ&Hu^fwK3(vG%W6FhXMZn%It@#(+ko8Vc4Na*1}0@JL7#9DLsQ5U*m>R^4k!m=6H zV59hArl7=7O+fDkhqE*A15a}M&OGt~$=G?=`sG|xvlkjf&24D-Zlq3Lr!3LBkk~Mu z8w0Z;`%qU_X>nRYScT9;CNUnUQh!5h9xgHBXCre!cj zJ8m51Uv33nn77Xa)S*8%TeZUXWZy}1M!@sO*sr(@-}Dz`i?|Q{St0_^EdlE`I&sf| zN;BaskrS9P!kkGma45g?H3GrcPDMj=xEL`E=nOhJPi5W4-vc=pE;o)n-m~X2hJ)NE zD<=>ZN7ruNH1Z7+RKF@Ip=vgUDSjwLPT)>Y?-Z=@TB=>cH`|-vM5W3O=gD22_oZlR z;7H9SfnF4pIQ4G;cAT7RE{m(DXa6&e*St{*3yRTqMk5@nuoKmif*Rf~DY6)$ATxAI z*_h=LM8VlJU1X&fIB@RP(&qI(Gi+Y`dCdc^x!sL`_Ti;cJd9WC@isU;@2~ERMIa{6 zx0?5x%1{bGQ(amnK9s^v??3y&>#fIw1d^@r;qTk4@o=kI_o|{c{pc{|gu^U*7dL~+ zmnDZY{6)}2w*%*U&ImNYsrzZAsNRO3d5I!@U3P106fur8q&zVGKX=eGV>ZFT++_?q z7E?&*ve&xLa;yLGlCggxY*ZiK3vUjkZkcbZ>VA8-4I{6iJf2ECwdP)HjhNANP{rLp znN7gKa$x5@Tr1N_)$r7-UoiFAw;n>D+cnaV#UXA6-*yIIuWsw;kpE}jB4{~bct+xc zr07s!FHelQQy?6i?5^^zw`GgRC{&)?(&lBY{$hvW%$Q)6kyp~*O;i}*feR{oMlkrQ zWs&DMqO265KLVrsp9_XSCQ+aZ+Wo<41h9TxQjjc#QpsJjG@M_ZAE#j78O+>?BqmlYzX=HZ}*T^cs)Bif+S?=pY$FU#C<}@6X;-P7$wjFvh9)pId?; z@qp_F3X&r0>~7|L`Xn7R>Gcrzr~DuwxDZ4gmwUSABs5~jWQYgqI*ykIdFf2R929&u z3dH}mK?n$T6;XGeIq%~oQbJQ*^s>xq91_mvO>X^3p9HT59#K8Jy1U`WeiR2-6cXkC zfC|C+`w!#lLJvY{&~8LGk}PZW+b5}JtdJJv8by+)9qs#zOl;35C4W$`ssGCsfmOaM z&z(k0UH%tJ&hE5wuA}$8fz1n-@<1Wh7otOs?t0MoN{?b%uEZ8KGLcZV5Ah$iD%Uxa z?Uzy>6^*?d{N6PQSKz|vcWZ8KKaxQ!OM{s%&(qYI6orLZ-8E*^65=)9zdxVMhrTI` zh^Ul)C@3ppXl>VAMyhtzN#816U`l@h>+ zDx1yVpFi#lw{)k9(s)diDi6q|A#KtLjK#GV31MG$vi9v zB2ixz#6b1AQ>j1W@y52=(9=e%okc#FK6~hQj;OrgyG{GPb7urQMiodlT>SPqf+SdU zuwAO&!@;D!vXb5YbBB$!z{0vWh6Ey&RVTh)F~;;P)F-00&CSKmNMBhpL#PIpG`H$hJFOes6R)3WhlF2 zwV<-u(e$-=echck%7;xPapg)JKKE(Fzp%MtTx1v`#r`G#c5eGIwExbL#9x1a<#_Qn zZ`U4S$#BSqN#X3Jx#oygD{EX$WafDk$fm*a*QoPQPjf5fb%o^%MT)nqWPF4A>SOA* z@k}qt1_zt6hB^2bflD%Y#J}0Jt(be4TF1biBZK(eZtlLC82z3}w==QC)FM3ig#5pd zd2seC`&zE+5h0a@!5JZiup-1=bl$+OxrkyqN!!3*l&SO$4D$WETA+wNP2E)%PQ!<# zL;B3|t(yVPtdBtjU8PPR)26NOpgHdDm1d8V3!iRCC8@Wws@rX(IdOU>?Ah(wL66!L zRkRNIU9OuZ_L7)dPr~{_CwOwN>?0J@osxcd}pSxtwji}Pj`zsf3ET*RixPr>r4JJd|#=TFd|2I|PQogRF+g+9_fK7EL`yPOpN-@W7U#sae8J_Yrhby0qZWk8ADAjzJAy_>gTp11!K zngqK=Pf+|$7r~>>+JR4Nf6}t7)F#5TI~&D@95eK}lciz%L!z8^o@-%2)!SeH3p|p`^WpM12H3$b-@mt*-c!a(lp8O) zshpjGG0L)L7AJHcczLruWxjZDba$UvJ{|mTAiq>!6f4i?17)z9=}bQl*o38I+h0P& zNa5b6NVARQTE*dc9nzQ@Fa2o|9qnmL`?BvrW4DzZJ;R;*mu~Pd+4Qxa1{k^YMT5yt zm?d=r^5XMsf@kfx1&32wcOvIO9Q@rk{*suiTr!2VRdy&*TrSmPoBJ&zY^u=dk2Tnc zhzvUy7p!Deb-v$>{(S+9am;Ij2EDKUqXkν}Dp&eT`3#2DIXLidLv@X2NEMIK#` zV#OzGwJIVB|L4W-1%1DPqIff!@8D{+BU0-o!f-Yz?!5-fkzpKb_&)v<8lV-d`SJ^s z_j+2iJcnl(;_SfbbySqoNp5MvZwmqsTfN6DM{YmAt$}*@pEkOx^U;}^|Hh1F#U+=S zl|%05dtZHg9=ni2Ns%{XWA2IjYewveAlF>8fx2UJBCWszll1Pk=}NTH#cHXpSu;a$ zy;sk2y~e-tGO*m|&y?og?Q#I#%$nU3kaZX;6i?(D_9$Z$&Wq=D%%5Tj7Y>^#vy>DJd~EzkZRE$IY9n%FtZE zgsunBvQkei7BhpZ9r-xCC1oH<*@Ytiv&mV`z?Tv)gSx5{VEXWf$QDqwSY{fs>K z)2BKI$fNllNcSM5(Pg;f+icMG>;W3e7{u(c(4v98w(?QZKgT9ZtlG3JHY7M9r}>op zT&r-9&pS=djvjx=ECtfs9DaL)_+O8OngFnL zr+QGkm4K_4KCQmZdhHAcZbm0Cz3pGW3gRsSodB2OUb%6_2+Tq!ouBF(!hC;tdW^%} zi0?|{ne~LwI>@GfKUt-?W?qje&ybRk zh-VO%FC5Gr4S;v2dBj~-0@^jWkT!zxG4B?Tg(gXUXO{^wuQ7>j;r>x#Tu zU*C`nzzCSv;5H9hrH<}%?&vG*=@jRvVXiwB(Y0`hpb#>LIchNCYdz|JA&cdJiB?udysNCjfA z(7m6zS3(b2Tqod6jWX+vFV+NXmVLtr2_uR)hDBeFziZ&*<15k3ey$4o{e61Go`YKw z=HtFlGm*X>>Jny{#kXy~I^Ntr_cSvzQ!@)U)vU2&QZ=6^~e7LSJic<^SP5azqP=^Wa;4j5ePR;EOa-k>OrFxwvHsDnn$4VEBzCf-j0Z#Ij@D1 z7kz0`;wDeSSLeDEK_wBL0odE|*+_onSehcFNOH-r)y9}tL1CLoKBz~>rtJ(Bkx;%l zHC@jjOG0cIov=SO>7kR??tfS)70(`N8ax0OIw zXiiD@5EITTEkdmAXaMw^@wnGWO?{@k_Wtg;s{V9aq(+ZUR^cmkY;cIztklydZ#2Gz z&rx}uxlOn;%LT}{8!XreD4gM}&7l2Vp^ioiqvInG5>HFje&Z^r6E!)5g(t0B%AF78 zBR8X?@U7sDf26|1iDI7D=|Zo0H_zH7tol>iedev2AIr*uo}rnKu=6kvq$LgC#n~Z( z@#^fNF~|#j-tJ^SV%J?ZH#gU2=sG2Nz%Y<6>^GHw2nVDP@A%pIt`VQ!Pm7+O8CN+^ zqHyRHaPY*g_O#)gl7lRL5Jh9Mwrr-d8vk6nQ$R7 zF{k5C^5i>c16k?d%G$-#fFtX9$tvq+|AAw<36saS$jSXWLm(9N$e^YGL)J%M2|NGd zoDvihv#wvw|Lw5hMR=A#e-et24B+~)WL+3mVv>K^8u*fNypvY6-nIYE3e0e0ZmJTE zU(xuIHNj(edJwj#S8c86nOz77Upd@{m723`8fpBx1*mV)M;o>@yw>tMYlD~W2S~>N zjCcWonxH4utvreFC2(hnc};=$;v=g2*y-kr%`^?XfA6QOi7Epx-1pC{(d0bFbB@RF z1r1$XTr!27tIYgp0W@*kDqT!ZH%^`O(MZrd_cK3W5G~PWMmL(6wA?q0c25ubDQd~? z*w$09I4<(3rUuaE6B1(eS*~>(6^JL-#}AeVF!J&8%7RbTu(1sFn@@rlw4(JItqFHD z-6zW_DHy(ne=K|!@4qu+zZ_Lxq)J*;&E{fCN=gRV;`xhFJ-zJkyFVmKKN0bW88Y&yB(P`-Qes7rl<=+x8+mO`PRDD)g6`TM@LntT{B(KaB8(~j2$Yt z)|uD(NlD;#OG?R*Zu4Dkmd`*I)5#PGxR^2WUp&7E<1&YRr5|IzdE-V)s}*!uS?N_% z;YDkZ=O9EhSL~8b@)b7EN};GEOs$RObH~L^&y%D48~aYp>0FBK?#zmg3SJzer6U5P zzkfepR+R(cy@$@b0Yk*plT3dr^G4U|Qn{cmyPXOuvWT43#l3`Lq0<{`x!fHBuG8g% zt&LtA?GOE3n?7dS)kuVA{K{mFR?k-Gw0?KE(q5yG5pjepZ-b>t&D5N*oSG*w3zz65 z#Kj$iZFK!+`575!Ld9w7a+(^mzdH1CvU250r3_T`4=veEF~~Ai?aMta%xH@=-ai^QeGa*kM5$w~OG7B+1k@aRB^35m#Ld|zFy#@9TDe`Jv< zs4E1(MYyEjiDYJ0Y9LQg^x?zB#fVT*w@EnF@$bE&IqMxy6P^1~3XDKoZ8mUcFp1UK z_7^QNuHmxPXSizH@Dks*T(g2~#QucnKV0FL&XX&8$0_va>(tSH9PO~*%FqQaG8*}? z{pfIW{LU1(em0)a$*`q?;PS zY|8O?{CLc=rKx7~fS2OcvHNDRpR>-`SQ$70`?Hy+`}v$T`w#a0jOv8g*sQ0XhBaX! z^+Mu}JY&uSNotSNjg7ml)VD6YIM{ws*^V4bho5qaJTBIp_N|*Q4`u~}<;tF!ZUN$Anm?@`4YYtq5uFBclHomNr}UW@9)v|PT}9Ykml7Im2TCYkBKeZ|843C?v7N7&fIFdCQ`LKloV#w z@A6bMKtvsA4l@gTE?t}j75=_fhr3m38Cjyk%p?`i@uG;GL+3t#C6SN1FG7P%s?4{$ zE?QSb+SB*c+?M$L5}mc7oMd&F@Ku(=ZC;~-qg|4ZYk1ug%Xg8H?Ypm381ZG$ zZ<9|#Vyz5i?dHBOdRT~!C61~rw4IpOduFWCao=js?Jdz^nL?acSYOt;*3vlk8yz3- zMMQNKAC;?zS2188#7RgmBpC+ootvH36gzFV;4h)OEv~ic8Z<+W4B#`^^Yy8?y9+%1 zp%NmNX3$0v@lTrRF64#1*&uPD6O)g?vUtvv-Z|Qc`xsYbbB8CLUtLr4-`9p8IHv}t zZDq={hEG~GNTIPAvMKL(KNS}%h2B&Zs19nQ<}{LSx{~W2%NC!L3fx3`bb_(nH~iiy zP_D?m1n;k=73P2>S9|5J`EN@e_^u+AxhRe(R%%m;%YvXeNw;s4lVeb28hcA@07=%o zy+K$Hbemb5VR5Tht*(mgA!HVf9^hZQF-cd9a0*?0X+r=HiS0Pe3yU*J>ba=vKYc2G zmQtbULrNRtOZg__sy+Q}v7{(B*O1jTf^n*{vQj;jcV#Ol+O7$+%c zSvg3LbAj**gg);9`uFtwumkOIYEH_zT5Muu9MY^0&VMtOPDK3)w@ygSk`9$(b?=P8Jlu{2mp*+9ac?# zXY7qh04KDO!|#lBdXL!o$7~P)F8$^VkuVyn^NaB22Wirv^F$&9(E9X$tibY_WNny~ z{;&sXUoxC0``on%ImMCXN+&ZY)e)SF>w_JU2kk!_v@b1KG^jiV#VrH?KDfaoVUDq< znX&e2Wmf^df`12In}}-ikF~ESwSyMt>YXg*Q>CtMZXtVLgW-FP`E+fa)^%V1L|sW( zWGwjH3;zjy8W|NObYew}sH~*M+%lW}Nk>n=)^GD=7Q^(fkR;)w;jI>IAdLhZ0<$S@ zDG$|!A9$x;-rw+RkX0>v_QENbN?F=#p$$%;25WPxXP|dtR#8<&cLrsAg>z4oqg#S=m-I4{VJ|&A`b{c-vk!N;;_VFb zU%u4*fSkESe0Z3U%1=)Z_>M*m_0|Jde6!QF0BhiALwL{FT9t^`wEAAMFT3{aTo%zj zE%36YuZJf`$=Yzf$Eh>ZQ90@pi4}XATU*bA%W;02mL~;XN3t@llV#SQ!TCGThYvRc z#;dQ34z(ZcpxYJcCA%@eyV{-M`={I4;^l@2>julnpFe+c=;-t1dpxuu$mpoj%^8Y1 zsAyk+CH)>1?7_7^lnU4h++8oLS>XZg26wJvR{(QF?Ei&TYW1Co5&@8=)}Tn(_m02* zsyl{tK`%mijLQ{l@;_uhg~Y&L;6*gjK^MP47mdZ4g5&30#&v!5{TBw`Y;lv$*CTjW zcfWrC@?$ikn47|gu;cXFa2|Yd^n6xl1wTO&32J{oZ6bf+TYQEb^@0M0?PaU0jJQ!w zpYf+8K5hhEBj9BnMU6P8|D$1lF?r7UGZkE>>924bosk`T%&jlZp*w|7 zV((HB^GucL!_0T)w8=0N@8jZOB|vTXOFwU_+FD=Q6gax7rN3eP;&cc=YmI}XE679+^1^;Kx@->>tXwhKWClGBO&9w?)<3`aU# zoQFZea;GWSH1ecDsrsJ)1>gWPA1_6_GwH1_0ewN+qKSO=o9SEe|KngeGp04rDzvE|Ksu3_b zx=mDBbjlYAvVzxSxVmAtNm6o6y52_S%Y`a1o^&iw7(h_fw1Q`D(rCP;S-Du~LLo4k z^V%1P!bI6m{%!9C*yIBiN%Qz>wBuW2rcj> zb4ji5$x`Nerjh%V>(A1dloY>Zo2-lW)qDU}z26KaDc%G`k$4JIO3D-!tt`NEu<|oW zaRaly3nh$*zSR5wm^#b2sMfBH+bDTJLQ0fwq@@M~>Fx%lyBh{n1f;vWhVB??rMr7z zP+({nVyL0sea`b7pZAL&Wac+Bd*A!M*SglV{;NifC`=%X$Wy@mz$HAXBC#dsm|3&T z@!C_maIiKV)5o_h->r8P4u5mX)^mMx?SdG!x3#r3Gn=lIC<2a*=?(>-n;p#tGF}Gd z%y+y@F{S!d?*PrE%Ah@^lrlgR*a?A3_@qbEG0|cJvVTOX!0%*wU@br?)#$qu{$PdA z`F4lT4Sg7HQyW2i9AlYYi%rk40G5}wo>PlYp`51f8R~jLoxY<(_dE-{w7%>3=90SN z{(XOS$XJ12l9ca8#w8)`vm1MVlRQ@JMby|LLo^k;VNIHeu}`!6rja0rtE($nYMx~H zV+?T1CY*{!N?lJb_hifYISx*w!%8zgC8c5w894vPI+hRijbY>bW6w14E_S!ngrk>% zT183ph_VmX=DcTi z-XvI^u+dZQpi*7Unp$16m;y$ceb0$KwH0!sU%1x*p!0r zCK68$W?xFacL(SbW5zkJ5FLX7K{6rOjgB-BxR(ki#C6 zumB@c_(tm)_BEIJq5|5`#?DUI;<^AF5=Gvxs%HrGm-uf2GbJzbP;Z@ejrA=a*|w{o z%+#qGaqKBBh@Rf!0vRYBO)6@RF3%8fRlThZKxQ@Asu5FyeAaVJqbRVF%X1Q#0gVfu z(NSsaYP#)$I=qj85h5wC?X-)9ymCBmsw+xp$)WhVT5xKs?JQf<0!t)$ImT|(RAV>L z3B>ixi@6%#9w3J14ru9V)p~u_(pu2TvcG?S1mf;=UeDi6;d6{5xkb{rR5}eVsV*jn%DIM6RM$*iQgv!NeUoF(IK0P0qaMN$)A) zgc{>goxZd~aQ>GuU*xxM-z=4>7>2a5bAFS7Od?G7t>xqcsJNVd=9zD@H%+OowD{Vt zAHGi8^j8xKP@-r-{;H8BJW$H!@|;Coh9?=foc{RnW4vo^A^UkRqm9Fj=h{JA$nfyU z_KV(#Ynrz@Nmyg4yx`t)?=|}C)R>rR^Ak}Zq4%PCn zcVV3OMat@4>TS_TX-^ft9|+fWq^F~sEX;W0K?|Kd``qTc!EPWIGSMVark%w>v>y`u z^;+Io%kJWQbYCAh8K&O&U=C8%=<`=$Q8uM;68Z=|n{a;9ASj$0tKodT_4|HcaHa7T zbXA7u`Yip8!}QW)`KV0cJJfc5CaiJ%esMkI_gwgR`=BU@P(tu!!HHD=;^A7zOqZOGd&@;EbTbxutM zZvXiClarP!3g;u| zSbY4Ysl1*rDnXxSkH|32i3tynGoFaSL>z3K%*@Q2o9pSmjAz(F&)XHm`*L#DN=kCd zKA4;LEc3A~TRn1F??0k@C03RYuM{&%&3tO7OU8}{1%6S2L^>?{x^GPv%J=c1{Q0=J zv{*g!BhG0otj*0GEJpQT5|Ng`pMuTB8Okoy-Vbj*19xkDqmamj#;YLQur1KI%2u>Q z$B3bTRUmvFAqQVyyhG6CuJ}VBkT6MqFYAj_>iVkjM9tjfvBx3sd#DOc8K>&J?(y+A zOcm$yx&-s*_0$4t>~*$-RCh=54)!)f*V{e zhA+n5??X%Q3~D0`Ugp{fkoa$1=~Kq%y*?-E(zFcaPVF+YTV;=Hd^C4H@Bv}P5Y`MYn-^$QoqTdr9_4L#7#vJYq zkc7u(&Fx{J08CAKEam>cq>y_tpRq5()j8^{tV|+Mq_r)R5-?aYYyW=^YT(~jbuXT_ z=Ow(;rdSEQZx+A~)_?QoZ~d$Q`3X+v++i`^RF-UUZy{TK`S_0^<{npgY>J%Lr7QQR zy|LyP?*HZ>_x^UmFn@Y-p)2#hLfRJA1FKI}F`z%M*&+hmNAJh}d=%*_17^;Rqi|t% zlWn46U)dpz1p3b>#c=wE-9sP6Ek~0eR~yqQjdHTM)X{#8H?$5d*B4oczS9qf@nZk) z^&kDC?)e;L->X0(Bh>8&3P&Xl*lH}EooAql!& znB+@k1~Mc2)U=%R?CVY1s7r(4z`)>F7V~%>zH?o zkTo}c^&%}z!}v|PPBa8t?dSC$Thgb9!p27!j!!Z(ori3{wYKDFCDxT&mf^L|drcQA zhj&tvbw3Ufz4E<_oM5pJTOZNvN_>Y|@c%Aolp~H+7Pg@86tl`K9r)G{@iRY2NJ0c0 zQ8A1KEz`Ev3wUTs!`uoo@m`2El*6@Cbca)Z_Y0Wq(6q#3pKgR-va7FkQJ0O79y`Gs zW0H{o|D<7K62CsYoUH^k5Y|Sew1Vw>GLWkfE2oa$D7|F^`PW@#^r2~YJ0g@j7hBbvQ`>Cudk*&?Md3b}ldq>)SR__<^GhMZqwrhSrEre=h5hnk&MwRh`Xh>5&A~e59mh-5dl7!;r z_P(blTIys8mmqX~A0EEM{#ATO8p}iFg<-4ZRP`JcyIUsl?E&{W!Q&;4TLBw=VPiY7 z{+k7TkYRI`3+-dQ8A!H6AhF+DR~AmeSuW*KYD)6OWajrlRHJYY^5!?4FsRNs2SlD#8NjkZ;B8nTf~HcLd@Z%0wel2dZJR*e@_#HW7CA46Ou)2Z}XIeGe5 z@;2%cuku6#ILE9Re0h0lXL>YywKl3eGMacD67NQeyva4S9O`6>fVMTmc$&K^gQqFLz8O>E1|6c zTRGno-V&*8ZV~rV%~{#@H!@#Z--XmlGJzqHOEdCQV=wMLB=Rv)RtjG6&#eggP`TcD zZOn$adV-9-=U1oIV5^tnMqZocYH^d62cLlL=f}QDD!=8rZ-;caXHdr#q1TxDthQG| z-p?i8!T#IVvFqhp=$jf_=XW2a7JP|tBj4Om{kvC)DM!qYz3&qkO#?T(-KkZPLeBWS zceGh2OD3LYi(H?^#V2OV(h{JJ2ODEwLw{DxeYCO|hJEVpe`Ve^99Wis}@ zW3(t?_y4vCAJdrL-EV8}eXmv?hk5E}8tYo_e~){pPuJ7yihy`%De#qC;+*qzcL|L^ zC|JIakA2b~YbyHf2!f}!f(|EG=z-pH+&K!rg0qXz+XKKTgG97p;#fJ2r z;j01*{3C(v?FR3bW-^FvtD56HTfg3RE!q<4MdiM>YK_Iv_tbGkIr)G*?Zt9-ThL9! z|2sjpboID%>O?UU#u~HVi=OHWbaxGzF2C-f;S_9~9{0dS0QAbUvF+Kl5!VG6p~r>| znQq$L@|%g_iH+r3d7!C!C~~{^eKFKoEw|C#n&dn;JWmv3Ru9Cb-7u+;v2zmKd<%cQ zBk`ll8#MMUsQ@Pd9G=|NCZl^LR#8rGH6m2Elu4+1S+`JiI=qc#r65ZV-{bu(7fjT&7i# zR5K7pqKC+2;^Ryoh!498$zV^q3iZ!(hW4n%V0FJ#H%za{ZwIwXBxkY zH6(Lfei1UJ;F13BA(o|dl2HOZR$DjQi@0X)P{}Ncy`sRT|1DZlL?2$xGs&?8)~kl> z_psKw^rq0Uut98pVzr5&Kg%hHw~+2_$}eV$1)pcQj~$}wHb}>thrz*iuTKdmgmvpQ znBAF-2>zczWsCh3+o}YTm{TV-@|!Eq@&h{S+Rntp2543M_|e?P#>UF(e=$>SFu<EYoeIGj^ZkonD_{F9z>KU*=Hz~Jl%e+Ce2aS?D{goFfLfX_bu`ANFUaSCpB zc5XUWF%6N1zdI!XHL9yqJf)pDX2-Opv$A8}Sn4nD$?c@0)<4M{VJY%g97^5Ee`j(bRTmuVIdg-W)-ydJ6T>aVd7YHTw z37u4jdr;C$pCCCJuL5zwr@s-i>I&FDTQ$+#BHegcW-p`NLpqjx2e_VqIm|wOB*lL@ z_~%;H{_~-eYqVApH1grobOdl19(u*cL7%nCexh|HjEAmNMqg8A@(6P)b}V!k*rV`u zf$Ju%GEM@)5fbvHPwegK{Sya&+5=iB`+-D&o<40m(B~c-!|zZ@(TomTGl#T%ap#42 zjc44e8*VX&4&qXWI-WXy=;28svCaNi7Cw4rPR`H&UXOcbmIU-Q)%Cb@Q!8k4GF_cR zj2u7G`n!tFZ1&}38Cv>TV){m{Z&~j2s+SB~sz5q7cC-uatvnWV(=4N$!WRR;LqgQT z@0oiT{+Q)!`Ac{fdS^jz-+tQ;jBS-|zn755bBe9k{u0$Dpr868&vl>m9dok=vyW%2 zbHRteNz^&D`J@}Na!W7GBVNHR7u7O5Y!w_FEGsMf=lZ`&&rb>OWQQ;qJBk-8)-olr zr`pk9MQzu;%JfhUc*HVuT)3z9AHT%kmppa!RpgvI_C>8EsCaGL>^(A7JLPegp4sG| z`yu)?ABeQEocke@au>u~f3?|hDl2~G>%c16A}P>oh!F^Pw9-^>Q?W9JYqE7e?_dnp z=;o}6kjt(y;{FlcIX*wV$XOL+@1TxFPV=1mNgiEqU$10{bjYRjBe0y@H`D)q5ZWSP zXJIVq@2Z=Mewx(7)leh6M?edv)d*(*Q;0D8>-+7-*AMb&R_ME5OU`_$DJcm`Y^ack zqD~xq6yQ&Z`u+I7`N=p7&CCP#mj_^QYbF-qpfTk0 z9qj6e6aT-LT1@%T?5A0W(enP~RIAj#@TtK{Eh?KR-M%!L?E7MW6^?n!&te|q9eVGF zqI5lZf_dV2vUo~)8vndK;*oLev65NR@o?a*iRV##dLgO6-*VPs5LzZ%vf;JL34ksJ z$ZhlWx^-wAvPqBSX7|*jjj{CfgoJvhpAR790MSKX9|o|8-dw2a=;@M@k_86^0gb6W zh3~thZ~)nf5+8pQ#o#$HcuOVv2<>l@Bf8`@Iq&b~5%kZxHWTTkr=R8Xu&~%52)!T3 zD$A@G6&VTaHHzP&=WP18r1%0yuy}a}bmzyvyz>F7>c&xbwVb_Ix_O{Gasz3Csf;Kx z<4ra~N*wuaB8we8iq89$De&&1vF6}T!I^|G+_cN7O;pI7S|L}-A`7)`n5fdSQamR- zjlD4Corm_r!Y7mfdlH0YXNV}DGa&1&5_KZdfHf-CwFK1L&gCWx^+oGL66OY z5?-*Uh;qDn6Jst5Kq$`6&f44C0mhAjyoe8KsoHrhHxT3MY`fxE4RG`*C@R3)!Q{zs z*@pbSh)iBzK6_UE=Jl%WsRhqdSj=mQ5F8f0`jpR~fBHHi4O=`WcoQuSk~yWLC~cR% z52Q@w^WC0AM@A~P`(1W+bphO+ez#vK9SPn2i<=D$f!HcJUeBye9?kv(W&Tv&3x8cy zSeTgDkeHep3e?X7S(!LF0TU01i<*m>nTu9uZ@tmT;&N_5<3o-pOa6*dqDgiO{uS@CeZ=6y3KY1kAnsVWC1(?KR@&Zm)q9BlqF+?h3@1!le*(d+gyV_KSUd# zX5?9f6S4G8mYEhQF_BXW)gWzphg01Yv51)cPI@DO7XWUN82F2_x$=*xwgam@>HPMB z9wT0BFRE(^_avSo_aIS%BJvKo?2R~fcwX~L7O>?n`FkH7urWc|cS zqkSNZ8x^HA+EiW+B>9%+Zth!T6N!1dlG=*H>_T>BufVe{vBZ+rA9QD9wC=GbNQPlQ zN|bF%ucOf8+r{!(FCQ3f97A<4ayrUO!CIcHQ0JMB2-I z;)wi@4%1JzN9m#mo1cflxcWg`J_D6$5=tX8KB)*t%bnp@566Fu)-aFM-oxk4X^^4q zm{q16K9+>8#)E(;dG&#Ta|?4@PL?{B#k7sR{~Ri{gQi`rM9y1VTK2V}&r4@eHj!z(3^xLoKl7!>vV4cr zMDztTD%7C|9r}&!r^jbr+p>v(6iLL9nwF*(=YKS5e)ow3iiDH%c)ii~-x*Hzzqy*~ zU8R#RakjKv=qLk}ONc_I&*k9En7_YvWpl&zskWpL>M^Uk&)x4Xeq`$ghmMt*T{-Bf zfXjLgBy4aKw9@RFJQ~XaJQ8=4=0ivTu&^@%Q@p#?uhU|Ke54iXmpVo_*g809Tj#46 zjSf~}W-1-6vQP8k=-r@kUW)i1k6ztOTTd0Y>O&8dvqjFaE?j>7dX4zVq*DD0s0hCV z`RwhVe6ExMDxK5OUssVpodJN{8MSysvgAsTjd!ecKU*WJTjZ^$aVuWm0B~9LO|F|8 zS+~bS94NQ7jgheDx%u{h;U@CMzETj&osncv1*|?*z;^s zx%PsLZ1R`-Yw+dIM>_KxxLCLZJ`EP9F8RUdIT-ebS~}2=yUo1eIM^C@r*q#`f$A+T zhTqxS`T+UQ*R^}6@comhs52O}9RA(EL=N%01JCdJmy6RUhBg~>^8uno*g~do<8C-I zJb=G4=lO3;X>6)%)P$yu$IPI&g$0DnV{?6I_xd{Y>bs10!_2>00B6UPNA8zPJgRwu zb)>AcT9pG%rFhVBrCY{le-3Td^a>XZTwD*T6;T^_IsSRQ_Lx%EOMZaSuwCOZ(}@Si zTWM<-a+5Lk*+vq%3f14ai`~7PCRvl9QCJ)PCl;u^hYqL*T!k{(bu`U3Zu=1(5R9F{ z7YiQ_T!YE1RTG}1f*qwEl<4m~^Hj^?qM?!Cey%Q;6A=-qaVMYU*`D>j;-}kSPKrvN zAeuSZrCnHIgXh6Hy1a(-E zL@=<s80N4nUtV82YYNrP|fg6ZAmQXHE4>60m`m&Xg+J92aG0Q_(d6%b~gsYCBa* z6dz=Qi(;lr8A*o%iAaAk$I2F`DGfC>35OozZnMoyUuD-;j!y8jU5cbx-z>Si-dNXcv;aCzJ_ z1Pd3s$nT3*uS6fM^#SE0029{WFw<-vz5!6?HYsHRW)iSj0))RPQlTh$yAo>C-3bsHo=*H>59#LEv6&W#zH!$Cx~}@ayczbV1LZ6c-uk zXjPTlU${zSyKI<@B0>is073r_iOU>T#w{&V1 zKBrvfg8-yIVh|wP@9ylNcM^+2LVgLVLx}k%VjaDW^TwN`8WI*pmU>5E${IW6x>t^O z?aLuJ+fa+;jxh1$RY}|fSgZ5NC}|zBGKJ{%d@SXR4IlX%tMx8l677nGdYe-V1aY&w zeTUa?!O&u!_kKdv()>jV(KE7FosC}Q~^~*`bE+a3<#R@i6#GzNeGh1T1+lA4X$g0l5 z%#0rYT=DW{R%SEq-cpTwMcT|u(Mvv+pFeXoI&3!^Ek_62LE8&$`7Ku!7Z+dM%Sbd! z)N(D69|0%fh2?S_zhi51)%p6|TXG>5Tb3sa z&kb9)UbOuBaSyJIkxpU~^V2FuT1xoiN@6Ul&zh|2rCdkS0I_RLH4is`{x}0b{bY}# zqb;Tb0|gh|n8s~aw2+z{ijK^8Yzw99?a<(JuR;K<)WD?4k`yLD^Es{ccSFJvMeL5N zsR?a70Es@y=Tf*X}GxZbdFY` z4lCO;En};a;lVhRX(=hwRRMQLYrU1m4Eh4eXL+bp@e?J=#i>~J9PgeH@NH+%)!9Cq zS^*=k48}^ee;Yu|Qh(`laz=UT{1gYr{${r-`lV>DLgQ%_8^AA63JMrWk=^FbH0@{y zZ>jed9+LApl&h7*`CzfL(=iGcZY_A4IH!1RXZKz%tFsk} zg>bGzS8k0O(xif460&3qf^A?)6$$$;L_GERzg5;GmwHm#O>=f@Ki>ExuE+x(*=N@T z-@S*DOr@jG_JG#80)^{y(c7GZ@AuN=4?Pd&OLD?(i&X9$@6kKzw+!`6KE1OOaYsKOs?@n0I~0AQa*wTE$owb- z&n`47YMbBb5e_BgC);g;Q?kZF$LTEL)2+E8{rKKfupfw!H72_A=*N!_{O9TRi#+NA zEx_lO8}KFjq%?e&t4*F(P$P!1#m<6V>$g#Rp`$d&Iy~(9R&Y|w zNyX{C*CWX>;cf1zgbca54GHFUdSo1R9+;feTJDVbMrpfl!(vJyI}xjpnk7txCJFvL zFNRZ(9Y~gfgG{V?Y#!>q0b5YduFRueM@?ET&R@Jfd*`*<_Q6pudzWl-emT zLnRZiTQ z-lV)BO3wE+Bt(7O&UWae&)C4r2e8v`6*H0nNJAyAg|s0<0JgvD1`4ed#kkyMC)5=2m8(uIPV5Tv?f5~aGULoX3 z7;bH4C0!P)O+rABmj%LFXp>Lkol3?~xZSsadF(Tq-6?|{Mb_+YJ)xUr&~OqZZ3gWaw9SD-ulNF= zXhSg?A#dq?&P}-325w2h*_rb{-LW??5Y~pmDQgc8h9a=iwm8DMq@D}n{+JtPh?VX=|Aq(lG?0T04efRX)ekFl(Y>UO{G z>=lpzkIEmR9AeH@A_J(6p$>-h4-i>E!VYBaz&Hzag=kGxNQ514peGW}B=>!v%e+JJ zZQ;DCw-8`(eIj?#BJoAt2nRQ=0zTBXu19Zv{v1eKJ+%v*@FmvNzeFC`s&c$9$yD;OrDB$t;hD;pZ7)I@L)!&qAcpj14Wkm&&Io*OV! zm1yFI<{g^LCy(cgeSQ!aaAn`!uPUF!o?nIO2k)30kJ6&4VyAtp!;F3|zk(?oaJw`! zlNg)^=LX=7fOU0l$Ky1>fz`R* z1YAXB2>5Q_Ttx#ze@tr%s6c*Gwa~MdU+rAC#8;q2elA;vxXm&4y zJU-rBZrgli_-(A+A9ZGnlJ6tuM{-U4Z-?U3sQ!R2$!u!5`4<7f`r1j%N9So+&1(*slL8`zRmOozI^xe zRDAp7$9<77LUx(1cE9a%Ni2x%{LR5~$Q2$1>~QRiEnRzKG%-F7QCz$gx)ze2@*-2PY_b5DTQY3!*4qW+u?dvA; zExDiwQyK0+IS(S>=$MyUTta+xbxj?5?#_&wTl8c5#zqt%yu%?A*iY6U-KCHox$}bZG%<#$lE5LAWuvtb|k#ZZg`#GNt zlVT!WHb>j+E-}MYJcqh|ws@MmGNfN0V2G9lJ#o* zNVT~DMTEnV0~3-BidDofBzy~OW!WGw7boZTbW`2M_fNl=$D7zGS10g$G)H@5PUztI7Fe73U@&H1V`PJ#;Lgw&fu$yGobgOI14 z<+1+tDb<@pfEdrr|2pBt3qWIm&CNlLG8dQh;BIKTb(ZW_zaw#1p)~1R0AUO0A{Pys zEMzvJ?S-TQt-rw+T2G32i&a8I&p5OAjp6vxkk^$WotgNhi>!Hun$U|{Ypzi(n z#Dx7<%t51ME|%ti3wC!Lgpg0(-SXUG6t4=jnh%-gUb`pci*4W)2MwR zBpe)|?0W9}+;X~1JDzLH7>2T&YCqqIWPvEgF6TMzquDq_R>q~G;az;?`ohNnflSMw zfZwG)MI`LaMC=+r)_TfFIMm?;^+W9<Kvb)ogK7&|LtH`2nh3(yb(BR3sPsQlnE<9K)ssMwpHC=|2a9E6GNfH@#_)F@V0mmbt__+ZyD1i7+vqEbhm@|NZOYx!k z(iV+s*qzN3cK1OB_-+~R1406Xw%&esw#vx+0M-&sJwe86t5$Sy;J~JLyR*LTcDh64 zkQ)j>U2(~Ty|$`9qO8-7=1^eYbKDnii>0HpJQ_Wq4$Gy6MYwbwPzSiM|K2=6G6SNi z@$b&@;mK7QLcWc9r#n%#L3@{(LcW#2RxY2+R&)lG3R=7-#KV>W$M5c{8ui<^-vKEz zVN^N2v(Ck{FRJ#F%T#Z`gNGfD^Y6-yr9&o4f#*PBq=*I{*Au=Kqg8I8+hC(9ci7^# zuh;Bm&D`q0pXSnlagLmN{CAtv@)e$gL5I?P&d6ty0~#_9^O`6}LVOT|=44$9t{e4s z3zMCbahvBU)hx*zQ`+xNcV_efGcy3kM#5vkpWj_x0C;y`+=3kJ&H=>w3_c%c;BOd2Q{|NedlTrZ~VvO_h##6m^oTk!G~?gbSTA1DYlih~`l&N4B~ z2j^U!s>8p1%Udxu_+2tZa!gWM?2^F@@;@$gRTVC*WDqv? zC}*9SvNTm!zcNrls&O3rBLW;gtgEiJnSzA-c#C~n*`5kX<-;UlmpV#Hp0iD&TpvUv zuq2<mPcwQoUyBQ)T2kcRxxxBWyd$Hs+aHRmK2}P z?BccFAlp804CY|K;hk>PcH42PG|~p`exY1)VI)kC4C;K`rG$~O+rUBxhSx=PIqK!Ipsd<=K$yTXX^GP}u)S0=vY>u9(c7V~ z>9{U4QAZ8d0;Zg(IezWsyEw5Wv;4VWr!`l*CE|NTjo|T2 zI-c1Wi!6*lT1}tF+6WfZN5_)^hfv|UQ-R9|=5feBXz7;<M)6qJ?h8bdsq_<%h?)?uG7@C$;v+6`^h1^9sWEZAOJz0 zza0eN^WRfHi(AQ43Chj=*nWKp77c)~Y9i=>@gjpcOtTt5Wbwi&afVw6P4Hzjir`}s zu{_H{bMN3$Gf8@lQ#*z&xB@GMrG*>F_OhWMGmm#MP*8 zsR<<9()piiKyd3NmXOdUf$_=!Q}iGKg};Ax4-#It`GKQqj^DvRHGz;-r{H}k7ZB%Q zV_|_0e@%-z1Diod-C!D3B5WoF|y-s69^Ec-xria^mFcI2C-1S zJQW}D@$CSB?MY>}-t-;ZQ{g1aSs<{O2vBEENdK#1U)B28F8Qm3)c5N)Ba_nJ1Uw5T zBrW@~wH1}7;05e0V+JlfWI~*t`Fy3d-L;^{FHG|BI2`LPo14+NINe(VyN!EVHE+X1 zO^Y0ABz@H^WRqEc+|I?$xFxc!)*!jAuEYj?C})Z7Oz^a-g!AuO+t4ye=F&q&$4dr7 zT9k1Ovz6>v(I)cewXVmoPIcq9^jiFYq1rXI#|x)LcAY-D#tK=FZYQ!DibszTW}ZgX z3o!GkW`U8i8Y4w>>C@L@vwH*Sc5;q<#ff``Ki)K+@&MYIFnIUVnu0HCVv3LIId%5^ zOsxmDCN^=kbax+8(o){e!-_<~7U*y3akH1E9zdN_CGmJk$HiZ;Xg^c~>}s&`&92C{n~Bk10j6ma+QD!sd|2Tt6{b#1`S6@rIs_dO4*T?UAf%*mquexi(9 zSV5iUgBsV(;g2PIEi8yRj6vLde3jZr5?9v+T5cMe=PWF?i@;NPo&W+yZb^uP*O&Oc83 zmjgv8r4zl=v@PkSYRgk6EeCU&uKt>3%(T&SOLGv8XM1K?S!@UEj6k59A6#sNmd89# zZ%nlpd@Uaq(vV0bC{SAwuNy0DcM0;CH%xjToy0M3V%9$!nJC#yD68%bYqpzVv|t?5 za}}u0>Zqn@wCmHgup$3H@ThTWBaM*JR_%^_82;7p%E+k3meIc-DxI z+FcP^Fn6pNExXvAG7=~Mu(12+C_0o@s;<wg9eRN}mO98wWGgS9ta-^({DzO$on57WY4VFy zV())idOsO7xoCm{&YJvhxa@s>JFHjQElbo84)9hJM`TI{D^S7k_w&oBLNZ`}WCC{I zxiMtjdus2iS@l9nlH^HxdI%s`g+(Pv+Dvdx3>=pjG9#Wmc>=@|-nZBIBy%bho;PT^ z#hmHyAGj;-FMgz!43D}Nm}l$UMAdN$WA8y zi#j||wn44jgY@i*%R|rqr0e|F?$SxC@u@Fu%jZ_sUoSb*gE{0Q=c3IK;k75{X39*B zM&NHE2~`9}!rA5cmAj&gbwR%KQkNPCjI6yqHQi}{R2nPt?D~hlK5Kdo_*bdjK^;%( zazGERQR3qTlzJM`6dRG8H-+O9w&-`;U`Wb<@?+u+;#gHQR!)a|!V#z2M&XzVi&}!C zxiypGc}ci&fP~vPA+qsGO$q&bfvE4gP)@r9 zpWqh>F$Ezd>1SF!mINVv9bK5<+r>>6+}rD&t~#Orn8@1m7*mHlZ0D3N(@o{&5C#&U*K5+*t3C1yi;L>7B+9FJ!`q-E(F1R3jU=St%%8fm2F@6XWP$c~>Dl zpC~|sG)TXD6Ri5L7T^?E_W__`L!8bgZxXQ4v#u3Wma89VTF8O1Yl+Hmvq1d;@pW6} z`CArNIe*dCTFKNRWjVA$W2Wpvjtx(NcDs^TJGFlESAdUBASUXatTt*s($sE9c(!M2 zbazN}CCP^mJjOD{uc~oR&0_1tYg&iJIt{RfAgT-l+SLUI8+MipDm%||tr0m(SJU0| zjO=_MiOyB*$XsqAe6y8f5%LgeC?sN~J%iM;MNuF1LBuk>@51Slu!YIE>7 z#BbobLK`F739#wBl-N+xhZ6*ArfYd!`CZp5B3=#I^u^EC(af3IT6G_@y^}?_^*nFKCFEyYT;1KN3gZt%JAr*= zOPC1An0%f1vObKpS&f_TMt1Ks2XA^>7U<<<1Tw41XMKp_5|Qnt>)|caZ1LXQ6=rQi z#nDY!CPH(1u?0^iEnAoo;z$uKCc@>|#pgBKb#mtI6>bAY+uW+%BReLJZEslFzn}Tk zZwfvdKXlDoPvElh`HyM$VjD4<88YA~TI^LiqxdvY)ry>g0`S4OAmKQb-AhYfuyU9p z3;S-apj)a1-{hB@BQrBk0?;U<;u2u>N`@!JV6@bxZ~?xx1i;O^p0Ae0U8L?(%R@^W zV;x;~uKIS5M+S zYpsV6VYL`lW(cD2A%75fX!3Vza=9XA_gzbhTHI6=IF^Iv;PPEkD~p>wtxy(;@rpG; z5}ON0;Pm-gyy$n>ifrm}@Q=3Lf*s#o|3%Yayp<07t3DDA>%d)UJiNAexl1Z)A^DPW ztzq@!ie*PUwn@t@i8#!nF=EYdBFafoZ3Nk1P@d4Lqk0APo!+$H>n5dSC1yW{zVcxO z>k^y=G&z6A4UueypCRsRV!Gge2S8?%L)p6%SvI$RuFJpXrfl`Usdf6j3d~ZeYiwlF zD7Gq6YHNZW0Wggg#dLP>6XNQ|#*sw%Mg?gNjkob*5seLrY=eOBK5uCh2z-H=KD*P_ z>su+noT|>#9bP82g6}TgQ4~##C+_ZS%5-`oT3Uda<>bg)yF~32m>D@S0SqYy{CDjF zF8wZ>0HknzAil%zlG(!px3ZE5pel+j4@7G<7Cgz!2?`=YPVD$=_&Du0`Q6`|thEoz zUC!?3d)e`EG4HR`mut;6fpzAt8AXmtx)c(xjg>r{gILqq*N2%2Ek~pF^8GTO4+f1W z%*U;m+d5pU1yx*7+3HJc`NIO+&P`9A)GeCp-eB6DiJk4x_#UPeN_Y_pxk`ITbkb|; zd|s*zY_0pO$w=>Ojg(wybqrfJJg)g!vGCIrB07D zK#{%{!bm7GSFTmzx&lJE4pVj6Y9-niHED0h(SbpJ-y+a_0@Jg-^q!RlRdB024?>B) z4&J}oeC7O^6~X-C%ijpi^iTz7x3cqLr)S}=B#E)pBKJLAY5riR2tmw zR#84DSlzA$-q|@hw0tAJzlgItYY#Ac2&kw6u0|Vvhy`4#iU5QA*i`crf-p4!gEN(A z`xqsxFB(n-@|t3Y!yT8FIZCN2jH2YUp~5NAqOcQ^U66X?&96k(7z9Mp)?7?}VGQs7 zUONNKFD|pWQ1A2VhAjE~G^pIr5GW55`i(6zvjm`{aExE;qt@pAbicZvv8OlcYQ4lC zL64fs-+qAICKRen?`_T0!e}95TbgzgZx-yaD~8S4#^&Q{lTcBv!?R(h4$SE{l;mSt zlxDu>o}bJ}sH(%y7xHpz-OEZ=$`ws^UKs<;SR6{3%L0f|N?Lt|rGkUuV_D}E!dp8Hj`C19hdBpyx2(DC><6DB zBx*sx^B}p(h$*>WN-0fHT=UU*bK%(IU^h!mO8e69WO9*_DWSR3?~meN8trSAM@LT$9S;(O0!M)O zO>xQ|Yq^PO{>&J)u2NgOQPkiZzZfHTX#Y%F;Wl)3Z_KC`yIIUZcgrBZ-cDo-#dgE` zMAE5gUsvY+VA|*)g}pic8&6Ad^Q4W4_RVjzefI9yIA-CF7a@mcT1ru@jC-)SDGFEh zq?7`^;$FdDZ>L^@QS~EzUkg|v?A6qP^O8jMB?HlF8#gdBsI$gsnsuPB97iE*Un~cs^>;SMWW;~v~da9wK$U-OU?I4vBq!gqDly0QE%OOR&yGuntx;uvMkZw?n0I-rzyI^{MUO*g zvuEwKu6@NB)tuHphm^1+x=6KZX{f2Lrc33m5Ti#i5Xm5t~d(w`}*43VqC}46I7}n&N z6AQPu9*Rz6e{q{i8fz-DQheUrF6U>wd2;bh$OMbjeZ$*o6*#oY%WLb$pYGO{Y6*T- zAP?tt86*?XF4sonhCZF+@>vAvN7c|4)M6n-3o?MR=-icw-`8_W=Cf`Bs4E%r)K0lV zIb^>|oXfG|dd4m$Ixpw+R~q}>lL=n}Kp9o`?&UBPBxTSTgw)gHnu5^;2b^KkCriA= zhgoZfkDA(jc}-3toV-YFc}Dh_U?7Q<*K-A_c6MmcMTfRMUf^ZBaGe)UrdRJ;uMwW6 z8U+Ap#MTo4id0Gxvr`I8ohpJ0OP|8*SDlqF8~*TEKJ4!eXEn~$l<<0- z(ptUh9%q^}`4Ly{vx4hN=aSpSc-7zI*KZiHm8j|!yx(binXQS>K+NiSKEUe|S3;m& z_8FMZ%-$m1Jh({z?t5`E)8ut=aJXz)Y*kaDWn=bSEB;&CY^Ly3gYsg3Ri~FsBv?HV-61}_$=a>7`5|%B?zKYSUl9X2^gtE$$pFo^@=V)Bc#Nz z8s8!ND?Pd!j=`3k;^tYnv@)%F!3G7z!4RLHT@&fgtOMtFqRJsi&Qzy3Z$ zOQ(|CKj-1n>Kz_Ga-|2%-R4?Siz2$F>b;whprt!sV{q}o`)a1zO2Q8S47F?BQ!lD5 zQX3p~Yu-;~Kg2CkEhQl#VKeQ1=k7GTBsO}TR5}uwz`B$t)(fS&WeG571Ni;saq5=I zznH#@5>JMg|kTCu&~3dLd8(Yz1orl+UG*mh!G1_R&q6Q5LK?tV znQw<#wao#{N~IZVE=@bltdDK0GjKC!Q0K9Se~qtoDRM3W2D$~G){8Xw8&2|7%SW0o z&iHg)+dDf2&RnlgceP@}+EXIm7}-^v@(}l0N;suMGy1TnL5x?=!n4wfAtczXADk?g zPI4hl5wu~#wfcTp;N1cR;&wh(a~Uqs?=`T)?f^ zbvj=cASfD!#fRJc7#UyAmM;A2%`$kuC*Z0$ICgSSZt!z84+hOSn&hG2u_Y!BFFU!GU}*w)pV#hL%dU6FkSj+_{`g z^j0hJSq~v>>twCl(>2nG?&0!;EC!SauLo4JIF2aqgRA?O7b=pZIG}~|3}1k1|7<=e zHYCl%6^~B)bJ0@*viTeplc0O(PneW5JP{YzduBX}!zMA}&&ysC@ar|(*IUmuByB6+ z8|WA!=}jFCN#h2TKUo>THHv3SOMGQVZPge@r&lkHiTt2isO<&s76P&@sf}+tAO zV{`9cFJNj<2Ng%BlHn14t?d#`6KZSUE240`G9d9CIY^oev>EZ6WmDKj$H%Rw;ddpl z_M2T79f2aIR*m`oO3c|w(UXf)>pUTlh0W$@#1^t|C{0(-io4N5X%t$pNE>+9x;OWn zH{o?Jg&B9m3iTKC&?TZMpgzMwm!WqyvsC$T#oO~ zW@^j+IKO@1f-i8DmmjLDKS-~nYH)VE>!;gHg39^oCUlP|@Hdy?o~KM8x?lGQ##?8N zY9S`C+#v|U`t$oH_lq?UFoFUmJZws5+uA4q4}eL4DTk9TYe6e6Q-knpMU`R2CEF*D zbI;4V_q&?r9|O6bWU$PC(JSoO<1w!8&C#3q5XXE&F8rH^3nkTe;R`{J>ta=@u@g+` zINAbQ)wIv0t`@O&PCy4-xUt6S2PFj-8ISGRypGa+ByKirWp=9a<&T%zUq6_^zR$nr z;|uAz7Wh^t>_>02(3JGrD+SQ!em$qWx)gw=UajxWOx(jJ63SRlt}W}0E0Saf7_Z}1 z<~NTSt+XJJC$x$Q%7ZqTJZl?s>$MK+^8HD#Ujuk`->A_vhN%vwsJZ-6`Y*yd2D2Vgv*|ZR3^a)?s9@ON(2(V$>sndqEsB;~qfeh;pBd`>3eT zGHH~Kv?fnjE}UYMnp|I2_{eE$YJ#f9d{624Z7hRcK@T${7@StQk7eGv8(d{NC2#tr ze_(*ltHte@J_oi%`HbxYL0sI=wX``c8oBf3PX489Smor?XSxvwx0IU%*XBYam zG5=6nA2Cw!v9VA@37v{ggq5Zb6%iXW5gC3he$`#Uo?cy-YUJPUlIhUt=yo^~tvqa> zqf^g8M?|NW+aJ9S6Wfz#|Izj%z6{d5vL6e7TW);P>trE#fn<3t@sfveUYxQ_G7)#c?!cCx6E2sy~E&%e4giuMSd*pqlFL=ku2%hLXAT0X1iztes@eqm&Wc` zmA7uoonv3W4$ao5(lPSeUA_|)Jx`sPpkrl(jDYDqwjk(X1K5lw)x;}>X zYAw`6xUH7>TKN_7eAp{|UBPrgB;Yj0nbC$8)ki0`On+bG;ZbxKcH0kO?42249}l`2cDQ7S4g9I z&$}_nW4}XBA&}VFRFUxVY-+i4PCnaOWL~XFzYOEgIdI?DH=tY2eehN{o#&SDZ9-Cf zc9T;mP*TfA>b0DMF;RFS9Z!zZT!Yb7;;2MHMB5TB4Hk&bXc(9FYd?pNRv8$eenW4E zZNiH*232_DnNwfCVykkoRoz*-Kp2=xzDlKwE^B0LmHp)7@u%!cXL>Fm@SA%2B1Fhp zL?g6RN7%DT(a$7s5ztRrx?iz1v32iw$RIB6N>eGX73V|_OF?q|T-`S%rKMCZ7jbEf z6;gRTXSq-xK0LpDkBf&(yUreBcpICHAMO0eXkO1}K(B#~p2xkn?(hV3d1f2bwlKuV zH^B>0dP;fhmRm*|D1fMx5tZ26XZ{Nw)_OU@lg)WQwGNu^*B8~)6e=%`HTZhUNyBuw zeBhJiCq)yb+RaoVUiC?WAi z5TqUxi8awaDe4*iw6k}Ldw(^U&SCNDQjnKtjV-RWm_>9zt11Hu{<~S;>HL_d=40`9@Vxo&z2Ap z33kpM#DMQgrZ8hN_uYyi7>dlbEBa=mzu*#dWId1HOd+w=AxtfsT;q9tsd67%S#}w* zrPiu1a&>tnR)a^1JL++e9ve&`XxnQ1&U9mSm*4mZY6kl?%FejTD4W=pIv>^&+e^*Y zxAwAktu{^naYHbGp<^BUZkE`s}9X;$i>X z)zT;pcH(vC*8E&@G&PJ)wT`x97AolV?$7g`Mn6EML_|D#LTqAWWn^sp$pgn2f=AHN z*(o6|+PhYAKUmYN&SkQhTRlfY6VK@X=<3Fi@I<=%L&{TCZv*R^v(56xrr*}Mk6rKb zp4u!7u2{Sog{jWWDAyRt2p@}u1qMnXeiBg6`>Z_Rud_m8vV$;!oHMjCBEmsh2``KT z9$AK~X7|ZVFOCBNqq3#XA=SsK9_i_rJ2V~QLzf(Hag@^lmLS23w;Tw<^4ow)9V zMRR(o|CE!K*R1fQ!bTl+& zo_o%xvk>>U5D49f$uM1&VlR{XX%#_<@x7ps&DVA#FGNIsIKCL(1CHa~G9pih1F*?i zye{B9T_YnEmi5vKP`>WenR?5qpeKW=+4it_*o@1@Q_x4jgZo{NjpWMFGyooSHu6)~ zaZXqI!nFhun^7*PdaZ`OZjLi%PG?z3jyJPr{wXWb)hdF2FNl+BQl1DpJQ{JZX6%O zJ+Cjwmzi|=MELD3^k^6O6xCVjKUt_$vU&V`rOwQk#$h>oi8!W#e>9&iX6IksZCilF zXD;&AmYtEGUj!K)I{-0cfm=hYq5_Q}cfCBM-H`Hwcm{fr}Tl?7kEjF}f~t=Y0YlkXjP2P~aHldi4g zkD2Bhh8SaUaeuL{$;8A&hv=CNV$vk zZ6{FQ#V@y7h8zx}G1$;%BU>bU83&%xL*mB9H15gu994`JB~lov(`#6|>}AdIKO6(m zn-+NB1%(A>1Zb9%jhYnL(iTs^Ap$c>;7%l=$Fs1Iq99wo%@9la)YeMNTApgbve2Qu0wPFaBD8qQ_b>6-c4+ zWNoCpUXXh>v4_V-00I_#i`8`fG<0^9$LVQDN7wTYf4YcPO1VTNgx`Kih<@Dc{z8M{ zEsBHd(WrX&=z%g-e19sh%h#9uvJanvLSnJV?IC&~LC(}i`SM)068z9qhjs7GO}d$= ze5}aN1%4HDGETw#*)j7}1@vz<=z5g*-k3hqyGndmT_9kmiGT|GDG#&bE1dH#F-IS< zC$4?yPFv}Y1er9h$w@*V&`YQhO6r& z!hr^~lIc|CDqX-Cr8F?879Kr!ouco&ch4W-t%KB()rN|2Zc8a=S`r9$OaXU+S>ev6 z{4CeUdh;OJXB7c}FA>T;te~ZWkPrShvkx^|k~1?^g8DWazWy}Px3(@7xK3f~lGXv$ zXpvf3v-1g#7<$O-U5&ZF1C$T4QGW$J#G8W64is$Sf(9cH7Sfd__ZU~_@ER-6FE$_U zFgHX5?xspn?lnIe&HXlyWd2F*zmyu9x=SNqLb)jqO&r<17!kG6nTM-1pSf~Zw{clh za&t?GuE(?1MA>y`p;%_%hJ)Jb*|Zs&D8KQ3Xu2=XUkETv-UPy%thle$duc7K z=QHI7G*1AxGJp2gUtydNP+!l7Sd6S2=b!JW;6`%|*!5#a3CTD~(R5_P*rFajd?(0E2UEuVWtNb&|L-1Aom+w_I3X$Vx1#Ab#7}K+yk4` z($X~Ho7_NjFZFXx2qZgc=i|R#K*!;1n1T~(Csk;hLqcI?)&vNI)6Uc7EO|^A?^Sk( zd3VF7CMUVL>F5TMB(qz~fLQ#iAt80*Z*`NC=<5o9r;|6%A#`)Bsv9lVN3Fx^OlS`= zSpmyY2L5n+9=Ag!Ro^XQhDwr5kKpI_!HCJqiR+R5JDpup$&YBAN45FYF!3;0WXLTUVQ zb@lJxzq6$kSV(t}MZH13#OGeSWfheAm@z^icvq(p4%rcUC|U6I$&+|>e%ZfA2)uEJ zh<({C6rVjIeqv#1*#2T6Zt%hR5fu~l`1D9rU}Q6kX~~F**_MPfWLm1cATTh?*O!eu zQJlp|E*rLGgp`5;bENlb72ad+0FCtL1%BfOyhl>DA~7L?5Es|L+W09cZjmcud0nC2 ze$8<(mKRJ>1fD-117Y%s+n_E{6&mA`X~u&S;-ECpoRbX+_4WOvoCAy5-##q$HB-aa z$Q47r9Qd-zm5mHcOXTy)J+saHhC}k@KOL|eET1B~weE_Gi>=z)NWI_1MunQ&yr_NUs-L+K>f}#pN9m6T;e@VTC;z2GF8wyliEE}ut@LT z{d#9Y{+K8-f~PMFPa!jnQ)aX`ovMHVz2)@k3oqLI9ra*1Bwc9?m@_-RifpC?Krhhl zLXwb?k&%)PXkY^ss=q&P?y(?i=;U~9LW6>&<>hP2Yr+D90r)V_-}Cvh>O&6PC(CGK zJ;;apo!Kx?ze}|a0`tg+CZf47Yck0o-M|9mDEEJAcoD-P%KR5`LJTa1V{en}*TJy_ zAfEdk9!$RSk}(L5hniHr#?$RXTP$wWRW*_M(|6vbnf2*euso;VwlRG@5$|$cu6W(& zP%CxFnkl9+R^pO7M)j+}+|p2XHHMd%n0WMp_1UvG8=bxhSARvPz`h?2QAMx&24NSJ zkB#UZ_r*dF4q{kMj zs!XUFUKK0IwIJ!JNlOxFT#Qsbm80|`@VNOCE3~z2B|H0b`<Ys#dI_S&S+g2r<02ulB%@7L|91lg#E} z>WT!C9Skln#>!phpJ^WJnqhtEEEj|S@7q8y9CZ>BT&T-bH#6#`N`g)#=-0a2Q$LL` z3F;w>wTo5uW!VmIQ#jlFdxAH*p8>aCJT&QcIUa)iM00LTsjceg+2$vzNk0qUl4lb| zdK}*?+8SmxSi<$mhAr{DZ`k=ykNE~s*RxgV(viydByFcvQmR`86$Fpp`>*&ZXHX8= zAp1FQP3ORP;s9jbMee^}IE3qKlZ+flPaJ>km^;MSzG9$M;&M}9Qmy-@Z}iA zR_vB4?U)^3hfDjLa4<~*hZsn80VE%{!6blh3&D}r8{@yUPpS$KsywC;tHP}YOF9v2bn76tHRmL3O44e3EeY(;6bIg z)sHWTSR8*w84&}J2D?Vzp8?A3DO6<*k4ZVi%%;6ts?>=76+f83mZ{b^NN4!vtOm7m zvZgBat*x!SRDtiY*6B8PE^RYFUB}GX?_Zq?=3=hO6f7_Z_iE%Hb)h;dL-OV$)#C-` z_VtZ=DHAhXCDbkv1Ptn*D2%O>&)P??IED`GO{N?FPKmwc?-kx{Dv~-FNl=$zdokRL zNk6x(kW^0h`yjO`hkkJ0tW2QrheJHk-&=SK0&y6`5x(c@rc$9QWPm*wpIIqSUL-fU zH8%iv_V(92Fh(9H{vdFs6L3%J8H+@euRoa7QQ_ewucA zO2DiuEpoT%??e6-(0(@2f=swylKvn$2d8D^CsB1w>s4_qzBxr~P_qMtjWYdXEtShp zy~?C6zl)UNX4b>|sAUOQN>FT}yDOjD*{KuA5ugCgiyuaKvi_$zow>`Tb8&v|O7o)K zWq%l&)(}I>?l$sZx;vUiF92(f)L{j5#~hJAA6s`doIITz=z>v{rsV1|!DaI%R1KILsSEOYcm&9&df+qbviu50wKUJv zvnrd>@V!)}hy=~fQsWYLFiMPBPvdcOUCK_Zsc|07W#+PX-S0rpi=A2F@A~rPV2LRw z2;bol4*EE|zxB_pi#2O3p`3c&^s|j7#A8a*EK@De1frl5a})ROc}qFGiUpviBDqE;VDs~25V|zj2INpg zy2!wcF}HT905@QNwmw5!@2dTHm0_p|_UrC(?r@Qux0#epf*<;I<}Qa7Z&yc08ovYI zDkdby|48x(E1l&;zK_wd`SU#E ztlEa)yM(g+E-<|Lr+3N!IzpP2E<9Q?mTV!2{j`+NOcRFPc`Ui$Mn?uj1yx0n{YBET zNuapR-k7SEr;#N^QHk+N+j1W zE9fHxkwQqvjPK62n4J`g-9;nFkc>y8%P)ZxU6&i&=djT%nLYA9=>szY{BD^4`d`C5#@PS!9cIk~4Q*`_(kN-dt_(J}Asb5C zgfwo0wgF;|`zVf2SmMp3g^<~t7pv}$uVe@YUMgie0-NA?=Hw^D#Eq_t{b1J5P)p|+ zR&Bw_<*_yyw0ca}TEqy&+5VM~*%SrqeQLqaa z@R*gV$^;&SKCMkhvgU@*G&``KkP#3RdM<%>PK*#b={@$PC1vxe5$@5v(4J^cpIG`a zHKv@UpsM{Lc8M@;hPZ*O^Qa@y-bTM^)pQ4vSElD<3{P_9h*nomYET~*>W_r|g3giN znpN+_6^G)nNE?sI{1ulSd19jJooyD%C6as-k(tDCj2dQ}OOP15+WnzsTm30bT&o$U z>WT{8Cfm-_5|rb{Pgb9g!o7|8&~q^Kpf&pqzB9gS)D9e5tX3Qr`(jGo=#9}js}f1g z-&7@II8ph<51Fr}rPD0F(@eA8k30r55?}8NXnnokT5ZFU8qaT&JtbqgP21iX+1(#S zuEdVp^ZS6{2L^W8x?8!r1pe+se1_T31(U5+(8aoa9~F)jduD%}Ry@?`H`;9CgY57? z{#5##)ujto5cwp=3He0Rhr}J_ekVfw+Ez*$9B)aBJU3hRG?Ij>xu60^Ogud9OW)RO z@g%^}a{tAg7^g*x16{uMCH6hRxr9e2P6FfRRMB@DN zu|<^@j+xuB)Aay1ATdYP7<=C;<_hVC_0NS2E?Q^AA-;BBS z{_Ep`?RdwJEuM#c(KO^%?VUYg0c1TrJzHHVGj!pRk;5ROZSIunHR6zwiF*~)im>PO zRG=HaHy4(u_MFn@xjuJAbKSHwh{C~*ox$Ugcq#%t(`|tY&Nq6nLOt1fV+s!bj3y{3 z+OPp=Qhis(wNHDuO=1|DImGBU9NoeN$7umu#x#jS1gX#j_-*XmunS+9%3%0LM4eQnhF- zQ!(L_N06z_f_>h(+HoLoaq;V7jmOCe36P4-5r@ja%}v&k%?2I3!uZ{>Cadi5?<&Kq zggfZr>9g@YYn@5{J@KT9ztns3HLG(A3LuiEUo$@HCrNCq#00c8QuT4zDip|};kwOa zygNHBu~_az;S)TyKU^}KCO~WZJouV|LiqJd?Ryea?f{T%{1rF#hUje-B zAf7%0P^#&G&io?1Q(N=|^b$Ed_UxIA7{O1~_ z>5gOl{jzqh09k>DC~!|+5a&|R^=XC8a^#c;)ryK5*1dlM23?o|-)HKM_BuN|g?)QG zDA+P*aUQ++wos<+*XwAmuCC5%!n}%RrfM_isBqj4M5AQ6*>xyw$~epPJmP2}Nof3f z?utlQ70I`lavZL^C(-!sMfdM|D>dogx^+p5<&C=5kzV$+aiW&J`cY)N@vRi(3+(2z zOFhdMF)j>)lHO=;S74ssm45!YP|tcEe7rX1<)(DF#a_Hx%MK`8U*g}!|JMunofQwI zj$E>vA>%WKZkrh!5A|NL=mgpbHRp;t$}K9F|EHcY+$OjKNaXR^f()spIX@Z*}0 zcNG>XTcxMv^ooTgiFF$W<|yhVy!ME6o~=(zJRR*yN|8s)<=9wQvXzIw(w});*q8`S zsM6LwaU&FVz0YdX@@b2G)1@8=fSa0r-FdmQVCF=Bt8p|ZgF#>2G{Z_iS9#=K#4!ItwuRsrfD&5R2hY?MpyA|R>Mx-ZyQq;W zwfz>6IOfzJG4daQHjnC$)ir)dhKtOv_z%?<@nNK#SBT24Aft`HeFpf_j9hK@tx;X} zVVe&LL_Vhsa@7S;I7FM_7NAAR%9W}b(ld^|7iZH;RQ(l^E!#eSOXnddesV_|3{eoO zD`)#b1CXAc1tHd9so7n_KRoDefMmUfs|>oI2O_xA`vit~m5*iUYvN+!pkZWYdf?YJ z>K~d+Oq>jer$BEpDa|~8w%CoBQY5R=B#cfPc;^1JIY6&v5^6>QKB-xT_Cj|z*9$f- zQSXTg01xkZq7pw)l1r;%%I*(b?f_vX=B1i{&%_uh@`5mE0-W4Rpfq;>?iWDHOTV1c zZ28437Nj0Gz9}F9izmaUSFf&hc~>E3AAGtk_;Re=3;E8%LMzwuE;ZC+kWuX=+XFnI zk=68#Q_x_?n*oSx3xUI*%f@iT=>6%5pZ&$!2`p3rDOVE^4wmjv6;`N41Owg-Q~dqq=d+nl%37Z;rw#T z7n_AnyYsc8fg?e^!Zh+4f-hdwDd%i~p>sHJEDjH5P-=@U4U^Ujij;M@(E+`+uNAY> zofxbY<>$<-n&0h_;{*e7xz`HxZA`BZ>_NgD5S|dhP^)5U`haSmW1OS6%p194U}gqU zZ}|}D>$_ac-B+xlG2~exydU>1omubJrOWQ@Y!U34$Ni~xEAV~*R3QDoH7$<}eyXA) zU8HnX!hJ@mDY@zwb1aTzRr9y^9P?l}dp^p;<+LLvI)%n_fOKgic)qil1?mE^9^d;e zTN5_+t4H3c$CDkB(QGT9y5pU58Q3`=A^>xamIu|2?)*JjUOO^pV`(8xo}zp#jkVM)?00#t!% zJj&Td4azGOdRgf$25k|cy<%gnty}XBY%`j7o^SG&3S8Xb?hBO*(Q9=_fEPGDAV^uZ z-uwZ)&Ape-zdNR6{ci|BX=!X+W3%tPs!^B&XO!JcahLPk~rFo{GI+Q+yQ8w~xL7u(ZY$@wL<4 z?cQzG2Z&$GUOO8tuMP4#J35puW@@d6wqCW5@+I`H1hYttLKH(hmXWbt;YRWHpkeQ5 zj+Zb}(Co9nx_c$>_9O!r0Qa)pL#JmA&7}=Cf6>LMZOXg7V8;f5;g?r%?}fW&k-TqM zs>cZ7-uwwODTWL78|njf4eR4mxwGrrKFoW{<|hlm313%MUbr8J6QeXlMeFJl5v8fg zF?uu~Q((^d0}^>e3b3vz}*4a4+eIXT90uehzcJysYl_?vu@oY~Xm zh;jCjw<`U2nHH6Mfe(dQ7B~h_0oQVjcczBfE%Xd`74Xu`=li;cBvBnv#ZC-G2sG4qbd@X5V+?#?j<>#a!?Qb##9%!ago`?z6 z4=pO?%9a)49btV6wd@Fgu-b@~>$XIKypp<5R?oNZ5}ua;ApmEC}=I;bA4=#-i3S74p1? zq{K4l%~vlO83A#Z+Gn)0z4HsC0&->8(WF)9v%Kv8`OnD`ECF11i{$W!k%U^1U}(*y zm2=gvrH*M-*Om(`y@Mt>DS0^JTVcv_c(gzs--H41DtM4CrcJq+M8RwuhnD_#&2QXb zNhG^%iohXJE|)Rs9^X*ZYk2FnV8iMu7Er&idg{B0O>=h|_w7=miJ?zE9P*W7v_$Tv zV0Q)a-vfT*hG1Zs#hW}zUv>H@r70b56?xW>!F~))Pfhw3skGtfjRZQN)1Ogjy~%pL zLh|oZZxmvzg=u+w*YfmTGHfA9=5u;(a&hJGG=b5AL#Qh?kl_RN3ZhSf7PPuJ63;pQ zyWM9Oucc39weJnEKGaN}Ywfv=<$R$T6GVZZT4N0K=DfwLCJU82N8`UemlBg_k7F4& zp=Zm|Ovcw~hf~(^{%wtcyYPCg%-Fqxp&2V`m^cm>I7@u)wYH$AnvC(k4(_*bnB+5C zSzfr@Lw2eV8y7MhrNxS{B2H5g$NVCLWTJ}pO6xwmji$ZI^H|Py33#TbD4k-f%US zJY(+DU^1lwg4-RAg#~v-xBmOMyFt5Naa5ZWTWsN8{+y-RV=LolRwE{d<%N@8kpjmt zL4N;F3%8FI=fRxv{qIkYR37@+C0U`Z#+&1#VDmaRR3mroNXRvnBfe_2gNgc{Gbj<% zCUhDdz@MFaOkW!x-4?qOcotx{--!OC>4C=ZmG`{YSt_@K@!D*nzUSqhZRfkp*F&Fg zjuTZLa6jD+nX)ArCJIXWxAfmy6QnKAQB7wks$D*&UOuiD4I+ZuwenX_#kC|ujJu|J zq@a{Pw}SuO?77=#tnZIA9YQd#er!b8dVN;~T1&Q-Mel5Gpurqf(3kMsATf$6R4!A~ z!B+9tN0ES1oz~MaMz1HsQc!~tCgVhVHcfF#FLgM+Jbf9L7uM(e((^!G{lr8*|c}B4;m2AgO7!f)WOH&5ec; zq5?dDJc(R?F81y%szHH!jmU9IIcJsM>7K@_#h%+Ny-LMO>upmpD8}?u51my~ReYKD z^~QQ$`_Bo=ZdoGMI9g55)7e&Ekx#8wn31&!meO`eQoC>{G7-X>}-{SA)iafNoh+%p{)o_87f}*;wXk z1Ln4#dvi#IzM+#ehR9d~7IDd$Ey-)rGw!EXA&WZe|4iS$!JbD&COKh$ef%B|F$Ck0 zOXZ?U^Q(6rz*K-qsnBdUHpNl+p`rL4#_Q47Q6#);-+cohEGA?>%TP&xFTr7Pbct}F za^Cnt-4#L(1k7GS&-Po#Uuo+|vejlyNTUisbjr%u%aQs!Hv6#O#WlkHIz-?{6L$Q} zR%_0K2IsxYjl--OQeF}P`<3rM?$5aFnO1%@kWK>q9NZ>-Xp4nH9(qU#c{O7-OQZ z59&48mg8x%S+uyUTjNF#@irPw4U+NzIO)kqJ-UO*fP5OCpX&8^F`~er3-^WOGxGNF zPUK3YfdT4LMMr8ou0)=cKl0mmq401S^%0QYFk*qCXM2|VhVN}C1DaN>2Q6iyb7Qr(=bma7ZHL(xDS zd}d9{ozI8LH8nMHaa#n9PJ7cCR*et`V?m$83bkN@J_06sjryhf2Kt~yApuD!FS^(T4Y~~w?O0U;SwC*0Q#<$gw&IDkPsOBi= z(2eFLCnd!(Xjxx`k>0#{GnAMO@XM@+bH}>Ey|+0mB{!nJ>TGl1yeSH1)@iXs7AKm! z^^KPR+w$6~s+f>QWds@yxy^I~#6t@R0i^Oc5^{Q9E*!7-WUmZ*IPbjFE4>`I0#sr> ze0oL2TN|Gc=p@|E#gZAIOP}j;a3HjoQvb6Ph5XVWcs{X>cRL#v`DNZ~@3q+<*2#@u zPfn|EXbwkm1gL%9V0Er6NuBc`Cm&b=LZPiSpZ5rnC)*Q8Y2Tg;)wzQXy~g}}2IhQ| zouFgBeaFy^2E~uJuue~bm;<%X1~*nlRn+=6VPMfVx{NIeqc$MNy|E-WEzg zf;zR)rN>=9g$GfVks}g=VNC?wQ7p#uBbjt~wx{Fpi^_3|j z*a18?up!^+>)RbfT(k-#?!hijc;+(fLq<)!G@fQ|%#A$)?)JpBfAnQ<+-OA`eZZYo z`j)$a$Z?XMMlO-0gFXwdMJ9?Fn5Vo@=?qz%HtJ8%M_~;xhWzUVT;Dc#yUGo%%$185 zt$U9M0@|EB9@kB(pc?GEm~pWgC)Pw=YFW5S6ouurhX!?Yd$c0_qa@_mD=z2-u>;Lg+R=BD};!JM9`a0t~Um8v{D^T zjvAP$eZs8s^YEjik1SPCTsF*|J!EnGZz|GGKl(sQcha#P6qcS=Uy!-HW!ETa3-u!1 za$&K7?0~%WcDm@cl2r>~;#3}oLi1Jn;CQBH+rv+qGc{@!CK7onc?ty&mp}U62a>SN zI+=!Gr>mDjNO1_5^y=-Y+(xpqy26wy*Y03p3G55rx#wN~SSxN6i-yy3`e%ViKt*2P zIRdde-N?HlbA(*I>aAwTShlyEsxTj*uT~k99|Ykx+jXUT_*?q7xPhcr_z{r%U(5Ir zAaNv?%gjNGQ@LH~&=YC!+xuiNu#{1mm&*@!OG=0?>o`{qyZr8ec=+rD7z; z_d_cYL5T}_laok)cSgab@JJ9b5_vraK@{ib=SN?G=`|WN(%DQO8D*~l9e=Bt+G@+; zwvH(yz@9T-1!wLlr{(zsdDa@UwyB8;tA78v2lgInywFIpPWSUvm66JVZgZpKPL;=k zuAbh4Eop?K$3)uPmHXMD_en1>!no(OEv2cGCBF+6u?2N-4K&L_i8(aModZsKM)R~& zQlqJ*Mw&ISsiMM595gnjqTrBLr)v^U0n~xapD%Oc9anCo-@tHpdbNrFXPaufzO_&- z4hCsebfT-){Kwu5Q78_ZG3BELO?GoGUhah!2b1}>yUR54L)Mjc$DQJsPt#g$uYs_k z`M@eeJg?LCbeYTk+>FcT&z~jP_*^H49+C26om_SVFViUC(W$yF=VAtxhL1OEz{-6> z)7ZQ}0g}V#!5`vb=PYgFle8p=<5fXV_?H;4>0Q@$65IUH$ay>^hY=s0entxTG@nk$ z{CgqkB}bYyxh7SVA{yeADTZ@Y@^t4sa_!|Vs{MPfl3l1})3~hGLTHJ%O2ceS&g8eJ z{E@a_YtOJBM3{2%JS^Tb2OU=vn!G2>dj6M!t0BW6|2ZkRO53bV)}mH`Z4c{w_DKA* zsShk9llYt*kITDFvA;j=c|bf|kL|v2eH-V^LaUR+@Q<4=XJzce%^4fHuqALfP{oRZ zk(?N4Xztfbe!6lent3-z)+JfY#1w`f*wzpKA+_9ilie12lXMgV>E9I^q{a|Wr!(Eo z)wVIBIpF*0))^_+v(VOxhWvHWzQyzmKy0@ndpf!efkS5#3&m&H702>D!x?U~2X6Y?7(WJF|_J{G;6&iaI=j~+-A zTjx1mBpqi)({1}KH(W!vF6ORD-hY{aKAisZg+J7_u?fpnv6xZ`&*!<6k{pFjRe$f` z^BU*f9IFh2LxyYV{*@k&0ur{!d?zF&bn3owMddRe-5HWB+Z7%8`3R2n#(*SvYwnf5 z2wzvek)wFUb@?zW-Csb&G4A{p-XuQs-5H=PVEvt0MUEPR&_=f3yDE<#|t@^4!DfvfKv`sunnchLFuQ}?BS zuAqBTP!UOJYYW%Edp$sB9jEVlMI5GdkF@r4JC|p;n`?;+=Wj}hPg0ium6HRo|UqMDjqW~v-!x3KEM=tfAP`R{e)tC*=fY&ih$-{zV7Xo z%Tpd=RT2R!X#OkFPys#Ow<2aR$pGSVLxa4Hu?Cq#ko#L zZ{__T)s$XXtxnDV?UvR%y8(}`zjk3?zw_^&!mLC<4MqNZ-*dXe#AIOM25GNkV`o=8 zsCT8 z*{=m4I`x{-FE1hAVV%IAk|ixR%RpFAaKXh!kHJo)y^Q5rhKOy`L3a9I7I{gJ!_{yn z;EtfrspNMBnHCOL6k_h;Y<~xrtLLWI?v--jZCR(a*u~7nM^r(Nh9$d}cxE0gm8$R6w(=M5F0KVR+EkNv+3Nf!t9s2q6{ z2(oyEjZ6RC%w7peN%y?3i+{ya2B=|`9%Y%`A9~&NP;+7YxipE4oXC5{CzU0l`_#vT z^FIB%|0?*FGTX;>cRqhk;Nq~;)jkZ-UeL^3pNs_t z8!-jS{B=Hp&wd^6&eVST1SD*to(X+&-sOFnAh-|YWTpF6i*)DO+TQObu?Oh`8`BrE z2?xEg487qIR5Aq2%w-AtRR6cNyxo8*@6%Vd5jaoT$mx`;-VSGq-N#V9Mmqe2W{FF^ zAl1|pa=Ed)7WaL2R`#KsKk(6LJR6?SfDWt<#Fy#+5C`L=E9B|n*_p=sXHH3MN8bB; zI#kF9Oz+#c*38})bB1V1LQl*HLop)-0$eUv3Sx`Y`!1%A*U1IF8tjhaD8z#47Yen` z$N)+}wa@K%E!GDg4WFr4RIkFYr{QcPkveIWf{`oMr(SVChJ0l*FxqOS zTIK(~!kZZ9ooU9+%JzYparIarq7{#4s7$|b;r;TdQF^)lvN&Q+PnSkM)%*0a0~nW3 zMTNOLn2qGlReLB*RTvHQ%NisI1e=ZK!BV(o5Y%^`ynf7akB!LD@W1=sK7enkC@6%d za92F(j<0pdlNS;aO6IUB&@4$hlDj5kFLc}-F?T!Lo1=@Onyb_I#qlao&Lcx~kr$}s zDbX;*Fl+GLEB_Pv&ZjU**d!^|r19x5xy@souOfd)WFK`$QtIja_;~w*)ucCp(IW1t zetlOdzelFGsBR>M*ucPm#n1ft0t1P=f+ap=!jkt$A8%F)U}lwrx5?ZsU@zsh4Y=5~ zzGE2bgqK8u_94Y`rhf7x4%$s9l$6^XbtzG9m&(C{$ z)rxQf>YZrdWs;yZOM4d`J$TmbC`G_SzWKI$&xlba>bgx^&fBz4*c2d$4{3N%2f?TF|F z(zYeVC1c2Lj>qzGFCp2hz7pX%$43hB<%cM8KTvk=S@Ak|7mEeQci&fK7_D#Uz3&5G zDcJewhEC8up2MOr-*iM2jK|pE+M_&m+v9XE+E{N_{PO(JC{L$x@p)eu5V4)^q<((} z5Ht2`v-RuDx@24%X{~Q={sE7DR@(Op<7z+tAmj`7OV0c?n8x2szY;+5dmj9npKAo( zh6yZgQPI&V05B3G>8-!u^XpegB5RKAbz4VhaxJZX>k&+^?yC#51&5T)a#Hdk@r2`M z#cC7=P`|FXYIKgW&nKpbRK#3l{5YDqsz-m4ggQ-jCT9!${!Qr4lZC)?91HIf*WpK- ztmy%uGh#DeMJE=7XOFMm)}pgB(TW1f4fnC1CUEFXGiudz0?E&Z&7%mIcqp*~p}(Gif_DLIsdJkz<9N z5Y%{PM?(3s^WN-Kp;53Fr%mr&Ri-b%=OD_M#RYL>mkmIh);=$Q%A83 zR2jN}0bQt8w8d%q)%6hPHw>F2gVAgxo0!AOSq^#~9!aTQra4uH`tV)E-*gR&kj)ha zq}osS%XIPvzeM`b>T_Roh9-~H=Wfq5o<)53rB^Rzvu?XnpdmPYut;e=57%yRl&Z0u zT3H}=qKb49X;IOsc`ug8Vzi=HM>LwpX+7e)Rb{r=pi!w_(kdQ4)oAkD|3%>3`)#X! z783RcM}o35*CyVZH;LtW6o4F=dXv{4h}+j#TkB%j`c)y31+kOJs!Yh?xUmDtkgB@u z)oXA}1ajl@P>x-o1R)jm0@7+1U0Hbyw3g3yrdaitUa(ulwZ8-9Mp;v{R<-%2_mCGd zBr)l`{AjjZkrc)Ygxda(QE^-S2bwPR0UPe=@8F+Hg^%c@hFZqAWWYS()$7-o7?;KE zboZp8^;bm5!@9-i`yjx896!OcgvP8w+aYJ|XHRq_ z7};(EbId!BUG`@q7sj2g+x|b=-ZCuewF@8BZ6X2+N=QkI2q+x_DiT8~-H3EINDSDB z2uL?biF7x^h%`vU&>-F2Fbrq8b-&mDoG<5mIbQpExBI=AVdnQd&wAFn*S+qW)D&O! zKP;fyc*_LH^Y`7hWI8uCXJnlTg1Z5{kwm_n_?##XToTZrXAL1XmQET)c?3$}lbJMq ze!4iD=l!BT$@<9Rr=2k+0DOMNW2 zx@fHnjZ7o8_&A!6x%?h@F?6x*cYza!b8@{5wr`HSH&V{}b|itGm`6=lpP(jeBqvS^ay3N(F{E&Z9cO z%C{+&$xlavlE)&HZt6s8Cc?6)Dp#lc`C`$6X?t9V-$F&PC2$k=`})Spyu?vvEv0_M zRIL&+Eo}1|?%l7F6`CGfE}zJrcwQ=xR!`Sbg?+aD&AoVW&~aKihC?_1d3_OjyyA+B1fjL} ztdmawH3_p^ie96$3xia9?B-aBZsq4Z5-#0}PPC`JW9t_r^>~?qc)!gkr%uJ4{$m&v zYO01+{�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