Files
prowler/skills/prowler-api/SKILL.md
Alan Buscaglia c8fab497fd feat(skills): sync AGENTS.md to AI-specific formats (#9751)
Co-authored-by: Alan-TheGentleman <alan@thegentleman.dev>
Co-authored-by: pedrooot <pedromarting3@gmail.com>
Co-authored-by: Andoni A. <14891798+andoniaf@users.noreply.github.com>
2026-01-13 11:44:44 +01:00

3.8 KiB

name, description, license, metadata, allowed-tools
name description license metadata allowed-tools
prowler-api Prowler API patterns: JSON:API, RLS, RBAC, providers, Celery tasks. Trigger: When working in api/ on models/serializers/viewsets/filters/tasks involving tenant isolation (RLS), RBAC, JSON:API, or provider lifecycle. Apache-2.0
author version scope auto_invoke
prowler-cloud 1.0
root
api
Creating/modifying models, views, serializers
Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task

Critical Rules

  • ALWAYS use rls_transaction(tenant_id) when querying outside ViewSet context
  • ALWAYS use get_role() before checking permissions (returns FIRST role only)
  • NEVER access Provider.objects without RLS context in Celery tasks
  • ALWAYS use @set_tenant then @handle_provider_deletion decorator order

1. Providers (10 Supported)

UID validation is dynamic: getattr(self, f"validate_{self.provider}_uid")(self.uid)

Provider UID Format Example
AWS 12 digits 123456789012
Azure UUID v4 a1b2c3d4-e5f6-...
GCP 6-30 chars, lowercase, letter start my-gcp-project
M365 Valid domain contoso.onmicrosoft.com
Kubernetes 2-251 chars arn:aws:eks:...
GitHub 1-39 chars my-org
IaC Git URL https://github.com/user/repo.git
Oracle Cloud OCID format ocid1.tenancy.oc1..
MongoDB Atlas 24-char hex 507f1f77bcf86cd799439011
Alibaba Cloud 16 digits 1234567890123456

Adding new provider: Add to ProviderChoices enum + create validate_<provider>_uid() staticmethod.


2. Row-Level Security (RLS)

from api.db_utils import rls_transaction

with rls_transaction(tenant_id):
    providers = Provider.objects.filter(connected=True)
    # PostgreSQL enforces tenant_id automatically

Models inherit from RowLevelSecurityProtectedModel with RowLevelSecurityConstraint.


3. Managers

Provider.objects.all()       # Only is_deleted=False
Provider.all_objects.all()   # All including deleted
Finding.objects.all()        # Only from active providers

4. RBAC

from api.rbac.permissions import get_role, get_providers, Permissions

user_role = get_role(self.request.user)  # Returns FIRST role only

if user_role.unlimited_visibility:
    queryset = Provider.objects.filter(tenant_id=tenant_id)
else:
    queryset = get_providers(user_role)  # Filtered by provider_groups

Permissions: MANAGE_USERS, MANAGE_ACCOUNT, MANAGE_BILLING, MANAGE_PROVIDERS, MANAGE_INTEGRATIONS, MANAGE_SCANS, UNLIMITED_VISIBILITY


5. Celery Tasks

@shared_task(base=RLSTask, name="task-name", queue="scans")
@set_tenant
@handle_provider_deletion
def my_task(tenant_id: str, provider_id: str):
    pass

Queues: Check tasks/tasks.py. Common: scans, overview, compliance, integrations.

Orchestration: Use chain() for sequential, group() for parallel.


6. JSON:API Format

content_type = "application/vnd.api+json"

# Request
{"data": {"type": "providers", "attributes": {"provider": "aws", "uid": "123456789012"}}}

# Response access
response.json()["data"]["attributes"]["alias"]

7. Serializers

Pattern Usage
ProviderSerializer Read (list/retrieve)
ProviderCreateSerializer POST
ProviderUpdateSerializer PATCH
RLSSerializer Auto-injects tenant_id

Commands

cd api && poetry run python manage.py migrate      # Run migrations
cd api && poetry run python manage.py shell        # Django shell
cd api && poetry run celery -A config.celery worker -l info  # Start worker

Resources