Files
prowler/skills/prowler-test-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.4 KiB

name, description, license, metadata, allowed-tools
name description license metadata allowed-tools
prowler-test-api Testing patterns for Prowler API: JSON:API, Celery tasks, RLS isolation, RBAC. Trigger: When writing tests for api/ (JSON:API requests/assertions, cross-tenant isolation, RBAC, Celery tasks, viewsets/serializers). Apache-2.0
author version scope auto_invoke
prowler-cloud 1.0
root
api
Writing Prowler API tests
Testing RLS tenant isolation
Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task

Critical Rules

  • ALWAYS use response.json()["data"] not response.data
  • ALWAYS use content_type = "application/vnd.api+json" in requests
  • ALWAYS test cross-tenant isolation with other_tenant_provider fixture
  • NEVER skip RLS isolation tests when adding new endpoints

1. JSON:API Format (Critical)

content_type = "application/vnd.api+json"

payload = {
    "data": {
        "type": "providers",  # Plural, kebab-case
        "id": str(resource.id),  # Required for PATCH
        "attributes": {"alias": "updated"},
    }
}

response.json()["data"]["attributes"]["alias"]

2. RLS Isolation Tests

def test_cross_tenant_access_denied(self, authenticated_client, other_tenant_provider):
    """User cannot see resources from other tenants."""
    response = authenticated_client.get(
        reverse("provider-detail", args=[other_tenant_provider.id])
    )
    assert response.status_code == status.HTTP_404_NOT_FOUND

3. RBAC Tests

def test_unlimited_visibility_sees_all(self, authenticated_client_admin, providers_fixture):
    response = authenticated_client_admin.get(reverse("provider-list"))
    assert len(response.json()["data"]) == len(providers_fixture)

def test_limited_visibility_sees_only_assigned(self, authenticated_client_limited):
    # User with unlimited_visibility=False sees only providers in their provider_groups
    pass

def test_permission_required(self, authenticated_client_readonly):
    response = authenticated_client_readonly.post(reverse("provider-list"), ...)
    assert response.status_code == status.HTTP_403_FORBIDDEN

4. Managers (objects vs all_objects)

def test_objects_excludes_deleted(self):
    deleted_provider = Provider.objects.create(..., is_deleted=True)
    assert deleted_provider not in Provider.objects.all()
    assert deleted_provider in Provider.all_objects.all()

5. Celery Task Tests

@patch("tasks.tasks.perform_prowler_scan")
def test_task_success(self, mock_scan):
    mock_scan.return_value = {"findings_count": 100}
    result = perform_scan_task(tenant_id="...", scan_id="...", provider_id="...")
    assert result["findings_count"] == 100

6. Key Fixtures

Fixture Description
create_test_user Session user (dev@prowler.com)
tenants_fixture 3 tenants (2 with membership, 1 isolated)
providers_fixture Providers in tenant 1
other_tenant_provider Provider in isolated tenant (RLS tests)
authenticated_client Client with JWT for tenant 1

Commands

cd api && poetry run pytest -x --tb=short
cd api && poetry run pytest -k "test_provider"
cd api && poetry run pytest -k "TestRBAC"

Resources