framework-compliance-t…
Make a cloud account compliant with a security or industry framework using Prowler Cloud.
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).
Claude Code
$ npx -y skills add prowler-cloud/prowler --skill prowler-test-api --agent claude-code
Codex
$ npx skills add prowler-cloud/prowler --skill prowler-test-api -a codex -y
Cursor
$ npx skills add prowler-cloud/prowler --skill prowler-test-api -a cursor -y
Gemini CLI
$ npx skills add prowler-cloud/prowler --skill prowler-test-api -a gemini-cli -y
GitHub Copilot
$ npx skills add prowler-cloud/prowler --skill prowler-test-api -a github-copilot -y
OpenCode
$ npx skills add prowler-cloud/prowler --skill prowler-test-api -a opencode -y
Windsurf
$ npx skills add prowler-cloud/prowler --skill prowler-test-api -a windsurf -y
name: prowler-test-api
description: >
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).
license: Apache-2.0
metadata:
author: prowler-cloud
version: "1.2.0"
scope: [root, api]
auto_invoke:
- "Writing Prowler API tests"
- "Testing RLS tenant isolation"
allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task---
create_test_user (session) ─► tenants_fixture (function) ─► authenticated_client
│
└─► aws_provider ─► scans_fixture ─► findings_fixture| Fixture | Description | |---------|-------------| | `create_test_user` | Session user (`dev@prowler.com`) | | `tenants_fixture` | 3 tenants: [0],[1] have membership ([1] as OWNER), [2] isolated | | `authenticated_client` | Django test client with JWT for tenant[0] | | `authenticated_client_for_tenant_factory` | Creates a Django test client with JWT for a specific user and tenant | | `provider_factory` | Creates one validated provider with provider-specific defaults | | `aws_provider` | 1 AWS provider in tenant[0] | | `aws_provider_pair` | 2 AWS providers in tenant[0] | | `all_provider_types_fixture` | 1 provider for every supported provider type | | `tasks_fixture` | 2 `Task` rows in tenant[0] backed by `TaskResult` | | `authenticated_api_client` | DRF `APIClient` with a serializer-issued JWT (use only for token tests) |
| Fixture | Permissions | |---------|-------------| | `authenticated_client_rbac` | All permissions (admin) | | `authenticated_client_rbac_noroles` | Membership but NO roles | | `authenticated_client_no_permissions_rbac` | All permissions = False |
Use `authenticated_client` for normal view behavior tests. It uses a cheap JWT and still runs the real request authentication path. Use serializer-generated JWTs or API-key clients only when the test is specifically about token obtain/refresh, invalid tokens, expired tokens, tenant switching by token, API keys, or unauthenticated 401 behavior. Use `authenticated_client_for_tenant_factory` when a test needs a cheap JWT client for a different user or tenant.
---
from conftest import API_JSON_CONTENT_TYPE # "application/vnd.api+json"
response = authenticated_client.post(
reverse("scan-list"),
data={"data": {"type": "scans", "attributes": {...}, "relationships": {...}}},
content_type=API_JSON_CONTENT_TYPE,
)response = authenticated_client.patch(
reverse("provider-detail", kwargs={"pk": provider.id}),
data={"data": {"type": "providers", "id": str(provider.id), "attributes": {...}}},
content_type=API_JSON_CONTENT_TYPE,
)data = response.json()["data"] attrs = data["attributes"] errors = response.json()["errors"] # For 400 responses
---
**RLS returns 404, NOT 403** - the resource is invisible, not forbidden.
def test_cross_tenant_access_denied(self, authenticated_client, tenants_fixture):
other_tenant = tenants_fixture[2] # Isolated tenant
foreign_provider = Provider.objects.create(tenant_id=other_tenant.id, ...)
response = authenticated_client.get(reverse("provider-detail", args=[foreign_provider.id]))
assert response.status_code == status.HTTP_404_NOT_FOUND # NOT 403!---
| Strategy | Use For | |----------|---------| | Mock `.delay()` + `Task.objects.get` | Testing views that trigger tasks | | Mock `api.v1.views.enqueue_scan_execution_on_commit` | Testing scan creation (`POST /scans`) | | `task.apply()` | Synchronous task logic testing | | Mock `chain`/`group` | Testing Canvas orchestration | | Mock `connection` | Testing `@set_tenant` decorator | | Mock `apply_async` | Testing Beat scheduled tasks |
| Problem | Impact | |---------|--------| | No task serialization | Misses argument type errors | | No broker interaction | Hides connection issues | | Different execution context | `self.request` behaves differently |
**Instead, use:** `task.apply()` for sync execution, mocking for isolation.
> **Full examples:** See [assets/api_test.py](assets/api_test.py) for `TestCeleryTaskLogic`, `TestCeleryCanvas`, `TestSetTenantDecorator`, `TestBeatScheduling`.
---
# BAD - TruffleHog flags these: api_key = "sk-test1234567890T3BlbkFJtest1234567890" # GOOD - obviously fake: api_key = "sk-fake-test-key-for-unit-testing-only"
---
| Scenario | Code | |----------|------| | Successful GET | 200 | | Successful POST
Prowler is the world’s most widely used Open-Source Cloud Security Platform that automates security and compliance across any cloud environment.
Make a cloud account compliant with a security or industry framework using Prowler Cloud.
Vercel AI SDK patterns for the installed major (ui/package.json: `ai` 6.x, `@ai-sdk/react` 3.x). The skill name is historical;…
Django REST Framework patterns. Trigger: When implementing generic DRF APIs (ViewSets, serializers, routers, permissions,…
Reviews Django migration files for PostgreSQL best practices specific to Prowler. Trigger: When creating migrations, running…
Create and maintain GitHub Agentic Workflows (gh-aw) for Prowler. Trigger: When creating agentic workflows, modifying gh-aw…
Strict JSON:API v1.1 specification compliance. Trigger: When creating or modifying API endpoints, reviewing API responses, or…
Use for authorized security assessment of REST, GraphQL, WebSocket, or SOAP APIs, including discovery, authentication,…
Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys)…
Clean and finalize authorized natural-language text intended for readers by auditing suspicious invisible Unicode and rewriting…