Files
prowler/skills/prowler-api/references/configuration.md
Pepe Fagoaga dce05295ef chore(skills): Improve Django and DRF skills (#9831)
Co-authored-by: Adrián Jesús Peña Rodríguez <adrianjpr@gmail.com>
2026-01-22 13:54:06 +01:00

9.3 KiB

Prowler API Configuration Reference

Settings File Structure

api/src/backend/config/
├── django/
│   ├── base.py               # Base settings (all environments)
│   ├── devel.py              # Development overrides
│   ├── production.py         # Production settings
│   └── testing.py            # Test settings
├── settings/
│   ├── celery.py             # Celery broker/backend config
│   ├── partitions.py         # Table partitioning settings
│   ├── sentry.py             # Error tracking + exception filtering
│   └── social_login.py       # OAuth/SAML providers
├── celery.py                 # Celery app instance + RLSTask
├── custom_logging.py         # NDJSON/Human-readable formatters
├── env.py                    # django-environ setup
└── urls.py                   # Root URL config

REST Framework Configuration

Complete REST_FRAMEWORK Settings

REST_FRAMEWORK = {
    # Schema Generation (JSON:API compatible)
    "DEFAULT_SCHEMA_CLASS": "drf_spectacular_jsonapi.schemas.openapi.JsonApiAutoSchema",

    # Authentication (JWT + API Key)
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "api.authentication.CombinedJWTOrAPIKeyAuthentication",
    ),

    # Pagination
    "PAGE_SIZE": 10,
    "DEFAULT_PAGINATION_CLASS": "drf_spectacular_jsonapi.schemas.pagination.JsonApiPageNumberPagination",

    # Custom exception handler (JSON:API format)
    "EXCEPTION_HANDLER": "api.exceptions.custom_exception_handler",

    # Parsers (JSON:API compatible)
    "DEFAULT_PARSER_CLASSES": (
        "rest_framework_json_api.parsers.JSONParser",
        "rest_framework.parsers.FormParser",
        "rest_framework.parsers.MultiPartParser",
    ),

    # Custom renderer with RLS context support
    "DEFAULT_RENDERER_CLASSES": ("api.renderers.APIJSONRenderer",),

    # Metadata
    "DEFAULT_METADATA_CLASS": "rest_framework_json_api.metadata.JSONAPIMetadata",

    # Filter Backends
    "DEFAULT_FILTER_BACKENDS": (
        "rest_framework_json_api.filters.QueryParameterValidationFilter",
        "rest_framework_json_api.filters.OrderingFilter",
        "rest_framework_json_api.django_filters.backends.DjangoFilterBackend",
        "rest_framework.filters.SearchFilter",
    ),

    # JSON:API search parameter
    "SEARCH_PARAM": "filter[search]",

    # Test settings
    "TEST_REQUEST_RENDERER_CLASSES": ("rest_framework_json_api.renderers.JSONRenderer",),
    "TEST_REQUEST_DEFAULT_FORMAT": "vnd.api+json",

    # Uniform exception format
    "JSON_API_UNIFORM_EXCEPTIONS": True,

    # Throttling
    "DEFAULT_THROTTLE_CLASSES": ["rest_framework.throttling.ScopedRateThrottle"],
    "DEFAULT_THROTTLE_RATES": {
        "token-obtain": env("DJANGO_THROTTLE_TOKEN_OBTAIN", default=None),
        "dj_rest_auth": None,
    },
}

Throttling Configuration

Scope Environment Variable Default Format
token-obtain DJANGO_THROTTLE_TOKEN_OBTAIN None (disabled) "X/minute", "X/hour", "X/day"
dj_rest_auth N/A None (disabled) Same

To enable throttling:

DJANGO_THROTTLE_TOKEN_OBTAIN="10/minute"  # Limit token endpoint to 10 requests/minute

JWT Configuration (SIMPLE_JWT)

SIMPLE_JWT = {
    # Token Lifetimes
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=30),   # DJANGO_ACCESS_TOKEN_LIFETIME
    "REFRESH_TOKEN_LIFETIME": timedelta(minutes=1440), # DJANGO_REFRESH_TOKEN_LIFETIME (24h)

    # Token Rotation
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,

    # Cryptographic Settings
    "ALGORITHM": "RS256",  # Asymmetric (requires key pair)
    "SIGNING_KEY": env.str("DJANGO_TOKEN_SIGNING_KEY", ""),
    "VERIFYING_KEY": env.str("DJANGO_TOKEN_VERIFYING_KEY", ""),

    # JWT Claims
    "TOKEN_TYPE_CLAIM": "typ",
    "JTI_CLAIM": "jti",
    "USER_ID_FIELD": "id",
    "USER_ID_CLAIM": "sub",

    # Issuer/Audience
    "AUDIENCE": env.str("DJANGO_JWT_AUDIENCE", "https://api.prowler.com"),
    "ISSUER": env.str("DJANGO_JWT_ISSUER", "https://api.prowler.com"),

    # Custom Serializers
    "TOKEN_OBTAIN_SERIALIZER": "api.serializers.TokenSerializer",
    "TOKEN_REFRESH_SERIALIZER": "api.serializers.TokenRefreshSerializer",
}

Database Configuration

4-Database Architecture

DATABASES = {
    "default": {...},           # Alias to prowler_user (RLS enabled)
    "prowler_user": {...},      # RLS-enabled connection
    "admin": {...},             # Admin connection (bypasses RLS)
    "replica": {...},           # Read replica (RLS enabled)
    "admin_replica": {...},     # Admin on replica
    "neo4j": {...},             # Graph database (attack paths)
}

Environment Variables

Variable Default Description
POSTGRES_DB prowler_db Database name
POSTGRES_USER prowler_user API user (RLS-constrained)
POSTGRES_PASSWORD - API user password
POSTGRES_HOST postgres-db Database host
POSTGRES_PORT 5432 Database port
POSTGRES_ADMIN_USER prowler Admin user (migrations)
POSTGRES_ADMIN_PASSWORD - Admin password
POSTGRES_REPLICA_HOST - Replica host (optional)
POSTGRES_REPLICA_MAX_ATTEMPTS 3 Retry attempts before fallback
POSTGRES_REPLICA_RETRY_BASE_DELAY 0.5 Base delay for exponential backoff

Celery Configuration

Broker/Backend

VALKEY_HOST = env("VALKEY_HOST", default="valkey")
VALKEY_PORT = env("VALKEY_PORT", default="6379")
VALKEY_DB = env("VALKEY_DB", default="0")

CELERY_BROKER_URL = f"redis://{VALKEY_HOST}:{VALKEY_PORT}/{VALKEY_DB}"
CELERY_RESULT_BACKEND = "django-db"  # Store results in PostgreSQL
CELERY_TASK_TRACK_STARTED = True
CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True

Task Visibility

Variable Default Description
DJANGO_BROKER_VISIBILITY_TIMEOUT 86400 (24h) Task visibility timeout
DJANGO_CELERY_DEADLOCK_ATTEMPTS 5 Deadlock retry attempts

Partitioning Configuration

PSQLEXTRA_PARTITIONING_MANAGER = "api.partitions.manager"
FINDINGS_TABLE_PARTITION_MONTHS = env.int("FINDINGS_TABLE_PARTITION_MONTHS", 1)
FINDINGS_TABLE_PARTITION_COUNT = env.int("FINDINGS_TABLE_PARTITION_COUNT", 7)
FINDINGS_TABLE_PARTITION_MAX_AGE_MONTHS = env.int("...", None)  # Optional cleanup

Application Settings

Variable Default Description
DJANGO_DEBUG False Debug mode
DJANGO_ALLOWED_HOSTS ["localhost"] Allowed hosts
DJANGO_CACHE_MAX_AGE 3600 HTTP cache max-age
DJANGO_STALE_WHILE_REVALIDATE 60 Stale-while-revalidate time
DJANGO_FINDINGS_MAX_DAYS_IN_RANGE 7 Max days for findings date filter
DJANGO_TMP_OUTPUT_DIRECTORY /tmp/prowler_api_output Temp output directory
DJANGO_FINDINGS_BATCH_SIZE 1000 Batch size for findings export
DJANGO_DELETION_BATCH_SIZE 5000 Batch size for deletions
DJANGO_LOGGING_LEVEL INFO Log level
DJANGO_LOGGING_FORMATTER ndjson Log format (ndjson or human_readable)

Social Login (OAuth/SAML)

Variable Description
SOCIAL_GOOGLE_OAUTH_CLIENT_ID Google OAuth client ID
SOCIAL_GOOGLE_OAUTH_CLIENT_SECRET Google OAuth secret
SOCIAL_GITHUB_OAUTH_CLIENT_ID GitHub OAuth client ID
SOCIAL_GITHUB_OAUTH_CLIENT_SECRET GitHub OAuth secret

Monitoring

Variable Description
DJANGO_SENTRY_DSN Sentry DSN for error tracking

Middleware Stack (Order Matters)

MIDDLEWARE = [
    "django_guid.middleware.guid_middleware",        # 1. Transaction ID
    "django.middleware.security.SecurityMiddleware", # 2. Security headers
    "django.contrib.sessions.middleware.SessionMiddleware",
    "corsheaders.middleware.CorsMiddleware",         # 4. CORS (before Common)
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    "api.middleware.APILoggingMiddleware",           # 10. Custom API logging
    "allauth.account.middleware.AccountMiddleware",
]

Security Headers

Setting Value Description
SECURE_PROXY_SSL_HEADER ("HTTP_X_FORWARDED_PROTO", "https") Trust X-Forwarded-Proto
SECURE_CONTENT_TYPE_NOSNIFF True X-Content-Type-Options: nosniff
X_FRAME_OPTIONS "DENY" Prevent framing
CSRF_COOKIE_SECURE True HTTPS-only CSRF cookie
SESSION_COOKIE_SECURE True HTTPS-only session cookie

Password Validators

Validator Options
UserAttributeSimilarityValidator Default
MinimumLengthValidator min_length=12
MaximumLengthValidator max_length=72 (bcrypt limit)
CommonPasswordValidator Default
NumericPasswordValidator Default
SpecialCharactersValidator min_special_characters=1
UppercaseValidator min_uppercase=1
LowercaseValidator min_lowercase=1
NumericValidator min_numeric=1