Skip to content

feat(sdk): Enhance dynamic provider loading and compliance framework#10700

Merged
StylusFrost merged 58 commits into
masterfrom
PROWLER-1391-provider-contract-dynamic-discovery
Jun 8, 2026
Merged

feat(sdk): Enhance dynamic provider loading and compliance framework#10700
StylusFrost merged 58 commits into
masterfrom
PROWLER-1391-provider-contract-dynamic-discovery

Conversation

@StylusFrost

@StylusFrost StylusFrost commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Context

Enables external and custom providers to be discovered and integrated through Python
entry points, without modifying Prowler's core codebase.

Description

External and custom providers can now register themselves through Python entry points and
run through the same flows as built-in providers — output formatting, compliance,
mutelist, and check resolution — with no changes to Prowler's core.

  • External providers, their checks, and their compliance frameworks are discovered via
    entry points and merged with the built-ins.
  • A provider contract on the Provider base class lets a plug-in supply its own CLI
    parsing, output, compliance, and mutelist behavior; anything it does not implement falls
    back to sensible defaults.
  • Built-in providers always take precedence on a name collision: a plug-in registered
    under a built-in's name is ignored with a warning and never executed.
  • prowler --help lists installed external providers alongside the built-ins.

No behavior change for built-in providers.

Deferred follow-ups: surfacing plug-in override events; a fixer-module contract for
external providers.

Steps to review

  1. Built-in providers behave exactly as before: prowler aws --list-checks,
    prowler aws --list-compliance.
  2. prowler --help lists any installed external providers in the usage/epilog.
  3. A plug-in registered under a built-in name (e.g. aws) is ignored with a warning and
    never executed.

Checklist

Community Checklist
  • This feature/issue is listed in here or roadmap.prowler.com
  • Is it assigned to me, if not, request it via the issue/feature in here or Prowler Community Slack

SDK/CLI

  • Are there new checks included in this PR? No
    • If so, do we need to update permissions for the provider? Please review this carefully.

UI

  • All issue/task requirements work as expected on the UI
  • Screenshots/Video of the functionality flow (if applicable) - Mobile (X < 640px)
  • Screenshots/Video of the functionality flow (if applicable) - Table (640px > X < 1024px)
  • Screenshots/Video of the functionality flow (if applicable) - Desktop (X > 1024px)
  • Ensure new entries are added to CHANGELOG.md, if applicable.

API

  • All issue/task requirements work as expected on the API
  • Endpoint response output (if applicable)
  • EXPLAIN ANALYZE output for new/modified queries or indexes (if applicable)
  • Performance test results (if applicable)
  • Any other relevant evidence of the implementation (if applicable)
  • Verify if API specs need to be regenerated.
  • Check if version updates are required (e.g., specs, Poetry, etc.).
  • Ensure new entries are added to CHANGELOG.md, if applicable.

License

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

…very

  - Implemented dynamic loading of external providers via entry points, allowing for greater flexibility in provider integration.
  - Added functionality to discover compliance directories from entry points, enabling external compliance frameworks to be loaded seamlessly.
  - Refactored check module resolution to prioritize built-in checks while falling back to entry points if necessary.
  - Improved compliance framework loading to include both built-in and external sources, ensuring comprehensive compliance coverage.
  - Enhanced CLI argument parsing to support external providers, improving user experience and configurability.
  - Introduced extensive unit tests to validate dynamic loading, compliance discovery, and overall integration of external providers.
@StylusFrost StylusFrost requested a review from a team April 15, 2026 11:30
@StylusFrost StylusFrost requested a review from a team as a code owner April 15, 2026 11:30
@github-actions github-actions Bot added the output/html Issues/PRs related with the HTML output format label Apr 15, 2026
@github-actions

github-actions Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

✅ All necessary CHANGELOG.md files have been updated.

@github-actions

github-actions Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Conflict Markers Resolved

All conflict markers have been successfully resolved in this pull request.

Comment thread prowler/config/config.py Fixed
@codecov

codecov Bot commented Apr 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.71429% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.96%. Comparing base (061fbaa) to head (fb22107).
⚠️ Report is 4 commits behind head on master.

❗ There is a different number of reports uploaded between BASE (061fbaa) and HEAD (fb22107). Click for more details.

HEAD has 1 upload less than BASE
Flag BASE (061fbaa) HEAD (fb22107)
api 1 0
Additional details and impacted files
@@             Coverage Diff             @@
##           master   #10700       +/-   ##
===========================================
- Coverage   93.96%   73.96%   -20.01%     
===========================================
  Files         243      110      -133     
  Lines       35653     8492    -27161     
===========================================
- Hits        33503     6281    -27222     
- Misses       2150     2211       +61     
Flag Coverage Δ
api ?
prowler-py3.10-config 73.96% <97.71%> (?)
prowler-py3.10-external 21.77% <91.42%> (?)
prowler-py3.10-lib 73.65% <96.28%> (?)
prowler-py3.11-config 73.96% <97.71%> (?)
prowler-py3.11-external 21.77% <91.42%> (?)
prowler-py3.11-lib 73.65% <96.28%> (?)
prowler-py3.12-config 73.96% <97.71%> (?)
prowler-py3.12-external 21.77% <91.42%> (?)
prowler-py3.12-lib 73.65% <96.28%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
prowler 73.92% <97.71%> (∅)
api ∅ <ø> (∅)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

🔒 Container Security Scan

Image: prowler:8ab4460
Last scan: 2026-06-08 15:36:54 UTC

📊 Vulnerability Summary

Severity Count
🔴 Critical 13
Total 13

8 package(s) affected

⚠️ Action Required

Critical severity vulnerabilities detected. These should be addressed before merging:

  • Review the detailed scan results
  • Update affected packages to patched versions
  • Consider using a different base image if updates are unavailable

📋 Resources:

@StylusFrost StylusFrost self-assigned this Apr 21, 2026
@StylusFrost StylusFrost requested a review from a team as a code owner April 21, 2026 12:38
@github-actions github-actions Bot added the github_actions Pull requests that update GitHub Actions code label Apr 21, 2026
@github-actions github-actions Bot added the compliance Issues/PRs related with the Compliance Frameworks label Apr 21, 2026

@HugoPBrito HugoPBrito left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes — see inline comments for the specifics. One cross-cutting issue that doesn't anchor to any single line in the diff:

YAML namespace unwrap only knows about 5 providers

prowler/config/config.py:244-253 only sniffs aws, gcp, azure, kubernetes and m365. Prowler ships 16+ built-ins, so twelve are outside the list (nhn, github, googleworkspace, cloudflare, iac, llm, image, mongodbatlas, oraclecloud, openstack, alibabacloud, vercel).

A github user writing a namespaced config:

github:
  token: abc

The sniff finds none of the five keys, falls into the else at line 250, github isn't in the safeguard at line 252, and the function returns {'github': {'token': 'abc'}} whole. github_provider receives the wrapped dict instead of the inner block.

This is a latent bug in master for 12 built-ins; the PR inherits it and additionally blocks any external plug-in from using the namespaced format. One change covers both:

if provider in config_file:
    config = config_file.get(provider, {})
else:
    config = config_file if config_file else {}

Comment thread prowler/providers/common/provider.py Outdated
Comment thread prowler/providers/common/provider.py Outdated
Comment thread prowler/lib/check/utils.py Outdated
Comment thread prowler/providers/common/arguments.py Outdated
Comment thread prowler/providers/common/provider.py Outdated
StylusFrost and others added 3 commits April 24, 2026 18:01
…iders

load_and_validate_config_file only detected the namespaced format for 5
hardcoded providers (aws, gcp, azure, kubernetes, m365). For every other
built-in (github, nhn, vercel, cloudflare, iac, llm, image, mongodbatlas,
oraclecloud, openstack, alibabacloud, googleworkspace) and for any
external plug-in, the full YAML was returned wrapped instead of the
provider's own block.

Replace the hardcoded list with a dynamic check: if the file has a
top-level key matching the provider and its value is a dict, unwrap it.
Keep the legacy flat format for AWS only (historical, pre-multicloud)
and identify it by the absence of nested-dict top-level values, which
prevents cross-provider config leakage when a namespaced file has no
section for the requested provider.
josema-xyz
josema-xyz previously approved these changes Jun 2, 2026
…er-contract-dynamic-discovery

# Conflicts:
#	prowler/CHANGELOG.md

@HugoPBrito HugoPBrito left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functionally tested this branch in an isolated venv (PR head): built-in no-regression, external provider E2E (local-template), external checks on aws, built-in-name precedence, and the PR test suite (235 passed). Two confirmed issues below, both reproduced by running prowler — the rest of the contract works as expected.

Comment thread prowler/__main__.py Outdated
Comment thread prowler/lib/outputs/summary_table.py
Comment thread prowler/__main__.py
External providers that do not override get_output_options no longer abort
the run with NotImplementedError. The base contract returns a generic
ProviderOutputOptions, honoring arguments.output_filename and otherwise
falling back to a provider-typed filename. Built-ins are unaffected.
Comment thread prowler/providers/common/provider.py Fixed
Move the models.py Provider import (used only in the shodan path) to a
local import so models no longer depends on provider at module level. This
breaks the provider <-> models import cycle CodeQL flagged after the
generic OutputOptions default was added, and lets provider.py import
ProviderOutputOptions without a cycle. The output_file_timestamp import is
consolidated into the existing top-level config import.
Comment thread prowler/providers/common/models.py Fixed
StylusFrost and others added 4 commits June 5, 2026 14:05
External providers that do not override get_summary_entity no longer cause
the summary table to be silently dropped. The base contract returns
(self.type, account_id), mirroring the get_output_options default.
Resolve the provider<->models import cycle CodeQL flagged (py/cyclic-import
#7267, #7268). provider.py no longer imports models: get_output_options
stays override-only and __main__ falls back to a new default_output_options
helper in models.py when a provider does not implement it. models.py keeps
its original module-level Provider import (one-way, no cycle).
… schemas

GenericCompliance is the documented last-resort renderer, but it read the
universal attribute fields (Section, SubSection, SubGroup, Service, Type,
Comment) directly and raised AttributeError on frameworks whose schema does
not declare them (CIS, ENS, ISO27001), dropping the whole compliance CSV.
Read all six fields with getattr defaulting to None, and dedupe the finding
and manual rows into a single helper.
@github-actions github-actions Bot added the has-conflicts The PR has conflicts that needs to be resolved. label Jun 5, 2026
Remove a stray '=======' conflict marker left in prowler/CHANGELOG.md after
the master merge, and move the elbv2_alb_drop_invalid_header_fields_enabled
entry from Fixed to Added where it belongs.
@github-actions github-actions Bot removed the has-conflicts The PR has conflicts that needs to be resolved. label Jun 5, 2026

@pedrooot pedrooot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! 👏🏼

@StylusFrost StylusFrost merged commit e3013d9 into master Jun 8, 2026
28 of 29 checks passed
@StylusFrost StylusFrost deleted the PROWLER-1391-provider-contract-dynamic-discovery branch June 8, 2026 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

compliance Issues/PRs related with the Compliance Frameworks github_actions Pull requests that update GitHub Actions code output/html Issues/PRs related with the HTML output format

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants