mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-05-19 10:43:03 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4ca5a9a942 | |||
| 482cb39ad3 | |||
| 03f731f34c | |||
| 0855534d59 | |||
| a4db8d98ed | |||
| 16f8e071c2 |
@@ -0,0 +1,60 @@
|
||||
name: 'Docs: Markdown Lint'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'v5.*'
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'v5.*'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
markdown-lint:
|
||||
if: github.repository == 'prowler-cloud/prowler'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- name: Harden Runner
|
||||
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
|
||||
with:
|
||||
egress-policy: block
|
||||
allowed-endpoints: >
|
||||
api.github.com:443
|
||||
github.com:443
|
||||
registry.npmjs.org:443
|
||||
release-assets.githubusercontent.com:443
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
|
||||
with:
|
||||
node-version-file: ui/.nvmrc
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
|
||||
with:
|
||||
package_json_file: ui/package.json
|
||||
run_install: false
|
||||
|
||||
- name: Run markdownlint
|
||||
# Pin must match .pre-commit-config.yaml so prek and CI behave identically.
|
||||
# pnpm dlx doesn't accept --ignore-scripts as a flag; the env var
|
||||
# disables postinstall scripts on transitives the same way.
|
||||
env:
|
||||
pnpm_config_ignore_scripts: 'true'
|
||||
run: pnpm dlx markdownlint-cli@0.45.0 '**/*.md'
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "markdownlint/style/prettier",
|
||||
"first-line-h1": false,
|
||||
"no-duplicate-heading": {
|
||||
"siblings_only": true
|
||||
},
|
||||
"no-inline-html": false,
|
||||
"line-length": false,
|
||||
"no-bare-urls": false
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
node_modules/
|
||||
ui/node_modules/
|
||||
.git/
|
||||
.venv/
|
||||
**/.venv/
|
||||
dist/
|
||||
build/
|
||||
htmlcov/
|
||||
.next/
|
||||
ui/.next/
|
||||
ui/out/
|
||||
contrib/
|
||||
|
||||
# Auto-generated content (keepachangelog format legitimately repeats section headings).
|
||||
# Revisit with the team — see beads task on markdownlint rule triage.
|
||||
**/CHANGELOG.md
|
||||
@@ -125,6 +125,13 @@ repos:
|
||||
pass_filenames: false
|
||||
priority: 50
|
||||
|
||||
## MARKDOWN
|
||||
- repo: https://github.com/igorshubovych/markdownlint-cli
|
||||
rev: v0.45.0
|
||||
hooks:
|
||||
- id: markdownlint
|
||||
priority: 30
|
||||
|
||||
## CONTAINERS
|
||||
- repo: https://github.com/hadolint/hadolint
|
||||
rev: v2.14.0
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
Use these skills for detailed patterns on-demand:
|
||||
|
||||
### Generic Skills (Any Project)
|
||||
|
||||
| Skill | Description | URL |
|
||||
|-------|-------------|-----|
|
||||
| `typescript` | Const types, flat interfaces, utility types | [SKILL.md](skills/typescript/SKILL.md) |
|
||||
@@ -28,6 +29,7 @@ Use these skills for detailed patterns on-demand:
|
||||
| `tdd` | Test-Driven Development workflow | [SKILL.md](skills/tdd/SKILL.md) |
|
||||
|
||||
### Prowler-Specific Skills
|
||||
|
||||
| Skill | Description | URL |
|
||||
|-------|-------------|-----|
|
||||
| `prowler` | Project overview, component navigation | [SKILL.md](skills/prowler/SKILL.md) |
|
||||
|
||||
+4
-3
@@ -1,4 +1,4 @@
|
||||
# Do you want to learn on how to...
|
||||
# Do you want to learn on how to
|
||||
|
||||
- [Contribute with your code or fixes to Prowler](https://docs.prowler.com/developer-guide/introduction)
|
||||
- [Create a new provider](https://docs.prowler.com/developer-guide/provider)
|
||||
@@ -32,5 +32,6 @@ Provider-specific developer notes:
|
||||
|
||||
Want some swag as appreciation for your contribution?
|
||||
|
||||
# Prowler Developer Guide
|
||||
https://goto.prowler.com/devguide
|
||||
## Prowler Developer Guide
|
||||
|
||||
<https://goto.prowler.com/devguide>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<p align="center">
|
||||
<img align="center" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-black.png#gh-light-mode-only" width="50%" height="50%">
|
||||
<img align="center" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-white.png#gh-dark-mode-only" width="50%" height="50%">
|
||||
<img align="center" alt="Prowler logo" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-black.png#gh-light-mode-only" width="50%" height="50%">
|
||||
<img align="center" alt="Prowler logo" src="https://github.com/prowler-cloud/prowler/blob/master/docs/img/prowler-logo-white.png#gh-dark-mode-only" width="50%" height="50%">
|
||||
</p>
|
||||
<p align="center">
|
||||
<b><i>Prowler</b> is the Open Cloud Security Platform trusted by thousands to automate security and compliance in any cloud environment. With hundreds of ready-to-use checks and compliance frameworks, Prowler delivers real-time, customizable monitoring and seamless integrations, making cloud security simple, scalable, and cost-effective for organizations of any size.
|
||||
@@ -22,8 +22,8 @@
|
||||
<a href="https://pypistats.org/packages/prowler"><img alt="PyPI Downloads" src="https://img.shields.io/pypi/dw/prowler.svg?label=downloads"></a>
|
||||
<a href="https://hub.docker.com/r/toniblyx/prowler"><img alt="Docker Pulls" src="https://img.shields.io/docker/pulls/toniblyx/prowler"></a>
|
||||
<a href="https://gallery.ecr.aws/prowler-cloud/prowler"><img width="120" height=19" alt="AWS ECR Gallery" src="https://user-images.githubusercontent.com/3985464/151531396-b6535a68-c907-44eb-95a1-a09508178616.png"></a>
|
||||
<a href="https://codecov.io/gh/prowler-cloud/prowler"><img src="https://codecov.io/gh/prowler-cloud/prowler/graph/badge.svg?token=OflBGsdpDl"/></a>
|
||||
<a href="https://insights.linuxfoundation.org/project/prowler-cloud-prowler"><img src="https://insights.linuxfoundation.org/api/badge/health-score?project=prowler-cloud-prowler"/></a>
|
||||
<a href="https://codecov.io/gh/prowler-cloud/prowler"><img alt="Codecov coverage" src="https://codecov.io/gh/prowler-cloud/prowler/graph/badge.svg?token=OflBGsdpDl"/></a>
|
||||
<a href="https://insights.linuxfoundation.org/project/prowler-cloud-prowler"><img alt="Linux Foundation insights health score" src="https://insights.linuxfoundation.org/api/badge/health-score?project=prowler-cloud-prowler"/></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/prowler-cloud/prowler/releases"><img alt="Version" src="https://img.shields.io/github/v/release/prowler-cloud/prowler"></a>
|
||||
@@ -36,7 +36,7 @@
|
||||
</p>
|
||||
<hr>
|
||||
<p align="center">
|
||||
<img align="center" src="/docs/img/prowler-cloud.gif" width="100%" height="100%">
|
||||
<img align="center" alt="Prowler Cloud demo" src="/docs/img/prowler-cloud.gif" width="100%" height="100%">
|
||||
</p>
|
||||
|
||||
# Description
|
||||
@@ -146,11 +146,11 @@ Prowler App offers flexible installation methods tailored to various environment
|
||||
|
||||
### Docker Compose
|
||||
|
||||
**Requirements**
|
||||
#### Requirements
|
||||
|
||||
* `Docker Compose` installed: https://docs.docker.com/compose/install/.
|
||||
- `Docker Compose` installed: https://docs.docker.com/compose/install/.
|
||||
|
||||
**Commands**
|
||||
#### Commands
|
||||
|
||||
``` console
|
||||
VERSION=$(curl -s https://api.github.com/repos/prowler-cloud/prowler/releases/latest | jq -r .tag_name)
|
||||
@@ -175,14 +175,14 @@ You can find more information in the [Troubleshooting](./docs/troubleshooting.md
|
||||
|
||||
### From GitHub
|
||||
|
||||
**Requirements**
|
||||
#### Requirements
|
||||
|
||||
* `git` installed.
|
||||
* `uv` installed: [uv installation](https://docs.astral.sh/uv/getting-started/installation/).
|
||||
* `pnpm` installed: [pnpm installation](https://pnpm.io/installation).
|
||||
* `Docker Compose` installed: https://docs.docker.com/compose/install/.
|
||||
- `git` installed.
|
||||
- `uv` installed: [uv installation](https://docs.astral.sh/uv/getting-started/installation/).
|
||||
- `pnpm` installed: [pnpm installation](https://pnpm.io/installation).
|
||||
- `Docker Compose` installed: https://docs.docker.com/compose/install/.
|
||||
|
||||
**Commands to run the API**
|
||||
#### Commands to run the API
|
||||
|
||||
``` console
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
@@ -199,7 +199,7 @@ gunicorn -c config/guniconf.py config.wsgi:application
|
||||
|
||||
> After completing the setup, access the API documentation at http://localhost:8080/api/v1/docs.
|
||||
|
||||
**Commands to run the API Worker**
|
||||
#### Commands to run the API Worker
|
||||
|
||||
``` console
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
@@ -212,7 +212,7 @@ cd src/backend
|
||||
python -m celery -A config.celery worker -l info -E
|
||||
```
|
||||
|
||||
**Commands to run the API Scheduler**
|
||||
#### Commands to run the API Scheduler
|
||||
|
||||
``` console
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
@@ -225,7 +225,7 @@ cd src/backend
|
||||
python -m celery -A config.celery beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
|
||||
```
|
||||
|
||||
**Commands to run the UI**
|
||||
#### Commands to run the UI
|
||||
|
||||
``` console
|
||||
git clone https://github.com/prowler-cloud/prowler
|
||||
@@ -237,7 +237,7 @@ pnpm start
|
||||
|
||||
> Once configured, access the Prowler App at http://localhost:3000. Sign up using your email and password to get started.
|
||||
|
||||
**Pre-commit Hooks Setup**
|
||||
#### Pre-commit Hooks Setup
|
||||
|
||||
Some pre-commit hooks require tools installed on your system:
|
||||
|
||||
@@ -257,14 +257,14 @@ prowler -v
|
||||
|
||||
### Containers
|
||||
|
||||
**Available Versions of Prowler CLI**
|
||||
#### Available Versions of Prowler CLI
|
||||
|
||||
The following versions of Prowler CLI are available, depending on your requirements:
|
||||
|
||||
- `latest`: Synchronizes with the `master` branch. Note that this version is not stable.
|
||||
- `v4-latest`: Synchronizes with the `v4` branch. Note that this version is not stable.
|
||||
- `v3-latest`: Synchronizes with the `v3` branch. Note that this version is not stable.
|
||||
- `<x.y.z>` (release): Stable releases corresponding to specific versions. You can find the complete list of releases [here](https://github.com/prowler-cloud/prowler/releases).
|
||||
- `<x.y.z>` (release): Stable releases corresponding to specific versions. See the [complete list of Prowler releases](https://github.com/prowler-cloud/prowler/releases).
|
||||
- `stable`: Always points to the latest release.
|
||||
- `v4-stable`: Always points to the latest release for v4.
|
||||
- `v3-stable`: Always points to the latest release for v3.
|
||||
@@ -338,7 +338,7 @@ Full configuration, per-provider authentication, and SARIF examples: [Prowler Gi
|
||||
|
||||
## Prowler CLI
|
||||
|
||||
**Running Prowler**
|
||||
### Running Prowler
|
||||
|
||||
Prowler can be executed across various environments, offering flexibility to meet your needs. It can be run from:
|
||||
|
||||
|
||||
+4
-4
@@ -10,7 +10,7 @@
|
||||
> - [`jsonapi`](../skills/jsonapi/SKILL.md) - Strict JSON:API v1.1 spec compliance
|
||||
> - [`pytest`](../skills/pytest/SKILL.md) - Generic pytest patterns
|
||||
|
||||
### Auto-invoke Skills
|
||||
## Auto-invoke Skills
|
||||
|
||||
When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
|
||||
@@ -81,7 +81,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
## DECISION TREES
|
||||
|
||||
### Serializer Selection
|
||||
```
|
||||
```text
|
||||
Read → <Model>Serializer
|
||||
Create → <Model>CreateSerializer
|
||||
Update → <Model>UpdateSerializer
|
||||
@@ -89,7 +89,7 @@ Nested read → <Model>IncludeSerializer
|
||||
```
|
||||
|
||||
### Task vs View
|
||||
```
|
||||
```text
|
||||
< 100ms → View
|
||||
> 100ms or external API → Celery task
|
||||
Needs retry → Celery task
|
||||
@@ -105,7 +105,7 @@ Django 5.1.x | DRF 3.15.x | djangorestframework-jsonapi 7.x | Celery 5.4.x | Pos
|
||||
|
||||
## PROJECT STRUCTURE
|
||||
|
||||
```
|
||||
```text
|
||||
api/src/backend/
|
||||
├── api/ # Main Django app
|
||||
│ ├── v1/ # API version 1 (views, serializers, urls)
|
||||
|
||||
+29
-29
@@ -2,7 +2,7 @@
|
||||
|
||||
This repository contains the JSON API and Task Runner components for Prowler, which facilitate a complete backend that interacts with the Prowler SDK and is used by the Prowler UI.
|
||||
|
||||
# Components
|
||||
## Components
|
||||
The Prowler API is composed of the following components:
|
||||
|
||||
- The JSON API, which is an API built with Django Rest Framework.
|
||||
@@ -10,13 +10,13 @@ The Prowler API is composed of the following components:
|
||||
- The PostgreSQL database, which is used to store the data.
|
||||
- The Valkey database, which is an in-memory database which is used as a message broker for the Celery workers.
|
||||
|
||||
## Note about Valkey
|
||||
### Note about Valkey
|
||||
|
||||
[Valkey](https://valkey.io/) is an open source (BSD) high performance key/value datastore.
|
||||
|
||||
Valkey exposes a Redis 7.2 compliant API. Any service that exposes the Redis API can be used with Prowler API.
|
||||
|
||||
# Modify environment variables
|
||||
## Modify environment variables
|
||||
|
||||
Under the root path of the project, you can find a file called `.env`. This file shows all the environment variables that the project uses. You should review it and set the values for the variables you want to change.
|
||||
|
||||
@@ -24,7 +24,7 @@ If you don’t set `DJANGO_TOKEN_SIGNING_KEY` or `DJANGO_TOKEN_VERIFYING_KEY`, t
|
||||
|
||||
**Important note**: Every Prowler version (or repository branches and tags) could have different variables set in its `.env` file. Please use the `.env` file that corresponds with each version.
|
||||
|
||||
## Local deployment
|
||||
### Local deployment
|
||||
Keep in mind if you export the `.env` file to use it with local deployment that you will have to do it within the context of the virtual environment, not before. Otherwise, variables will not be loaded properly.
|
||||
|
||||
To do this, you can run:
|
||||
@@ -34,12 +34,12 @@ set -a
|
||||
source .env
|
||||
```
|
||||
|
||||
# 🚀 Production deployment
|
||||
## Docker deployment
|
||||
## 🚀 Production deployment
|
||||
### Docker deployment
|
||||
|
||||
This method requires `docker` and `docker compose`.
|
||||
|
||||
### Clone the repository
|
||||
#### Clone the repository
|
||||
|
||||
```console
|
||||
# HTTPS
|
||||
@@ -50,13 +50,13 @@ git clone git@github.com:prowler-cloud/api.git
|
||||
|
||||
```
|
||||
|
||||
### Build the base image
|
||||
#### Build the base image
|
||||
|
||||
```console
|
||||
docker compose --profile prod build
|
||||
```
|
||||
|
||||
### Run the production service
|
||||
#### Run the production service
|
||||
|
||||
This command will start the Django production server and the Celery worker and also the Valkey and PostgreSQL databases.
|
||||
|
||||
@@ -68,7 +68,7 @@ You can access the server in `http://localhost:8080`.
|
||||
|
||||
> **NOTE:** notice how the port is different. When developing using docker, the port will be `8080` to prevent conflicts.
|
||||
|
||||
### View the Production Server Logs
|
||||
#### View the Production Server Logs
|
||||
|
||||
To view the logs for any component (e.g., Django, Celery worker), you can use the following command with a wildcard. This command will follow logs for any container that matches the specified pattern:
|
||||
|
||||
@@ -133,13 +133,13 @@ gunicorn -c config/guniconf.py config.wsgi:application
|
||||
|
||||
> By default, the Gunicorn server will try to use as many workers as your machine can handle. You can manually change that in the `src/backend/config/guniconf.py` file.
|
||||
|
||||
# 🧪 Development guide
|
||||
## 🧪 Development guide
|
||||
|
||||
## Local deployment
|
||||
### Local deployment
|
||||
|
||||
To use this method, you'll need to set up a Python virtual environment (version ">=3.11,<3.13") and keep dependencies updated. Additionally, ensure that `uv` and `docker compose` are installed.
|
||||
|
||||
### Clone the repository
|
||||
#### Clone the repository
|
||||
|
||||
```console
|
||||
# HTTPS
|
||||
@@ -150,7 +150,7 @@ git clone git@github.com:prowler-cloud/api.git
|
||||
|
||||
```
|
||||
|
||||
### Start the PostgreSQL Database and Valkey
|
||||
#### Start the PostgreSQL Database and Valkey
|
||||
|
||||
The PostgreSQL database (version 16.3) and Valkey (version 7) are required for the development environment. To make development easier, we have provided a `docker-compose` file that will start these components for you.
|
||||
|
||||
@@ -161,7 +161,7 @@ The PostgreSQL database (version 16.3) and Valkey (version 7) are required for t
|
||||
docker compose up postgres valkey -d
|
||||
```
|
||||
|
||||
### Install the Python dependencies
|
||||
#### Install the Python dependencies
|
||||
|
||||
> You must have uv installed
|
||||
|
||||
@@ -169,7 +169,7 @@ docker compose up postgres valkey -d
|
||||
uv sync
|
||||
```
|
||||
|
||||
### Apply migrations
|
||||
#### Apply migrations
|
||||
|
||||
For migrations, you need to force the `admin` database router. Assuming you have the correct environment variables and Python virtual environment, run:
|
||||
|
||||
@@ -178,7 +178,7 @@ cd src/backend
|
||||
python manage.py migrate --database admin
|
||||
```
|
||||
|
||||
### Run the Django development server
|
||||
#### Run the Django development server
|
||||
|
||||
```console
|
||||
cd src/backend
|
||||
@@ -188,7 +188,7 @@ python manage.py runserver
|
||||
You can access the server in `http://localhost:8000`.
|
||||
All changes in the code will be automatically reloaded in the server.
|
||||
|
||||
### Run the Celery worker
|
||||
#### Run the Celery worker
|
||||
|
||||
```console
|
||||
python -m celery -A config.celery worker -l info -E
|
||||
@@ -196,11 +196,11 @@ python -m celery -A config.celery worker -l info -E
|
||||
|
||||
The Celery worker does not detect and reload changes in the code, so you need to restart it manually when you make changes.
|
||||
|
||||
## Docker deployment
|
||||
### Docker deployment
|
||||
|
||||
This method requires `docker` and `docker compose`.
|
||||
|
||||
### Clone the repository
|
||||
#### Clone the repository
|
||||
|
||||
```console
|
||||
# HTTPS
|
||||
@@ -211,13 +211,13 @@ git clone git@github.com:prowler-cloud/api.git
|
||||
|
||||
```
|
||||
|
||||
### Build the base image
|
||||
#### Build the base image
|
||||
|
||||
```console
|
||||
docker compose --profile dev build
|
||||
```
|
||||
|
||||
### Run the development service
|
||||
#### Run the development service
|
||||
|
||||
This command will start the Django development server and the Celery worker and also the Valkey and PostgreSQL databases.
|
||||
|
||||
@@ -230,7 +230,7 @@ All changes in the code will be automatically reloaded in the server.
|
||||
|
||||
> **NOTE:** notice how the port is different. When developing using docker, the port will be `8080` to prevent conflicts.
|
||||
|
||||
### View the development server logs
|
||||
#### View the development server logs
|
||||
|
||||
To view the logs for any component (e.g., Django, Celery worker), you can use the following command with a wildcard. This command will follow logs for any container that matches the specified pattern:
|
||||
|
||||
@@ -238,7 +238,7 @@ To view the logs for any component (e.g., Django, Celery worker), you can use th
|
||||
docker logs -f $(docker ps --format "{{.Names}}" | grep 'api-')
|
||||
```
|
||||
|
||||
## Applying migrations
|
||||
### Applying migrations
|
||||
|
||||
For migrations, you need to force the `admin` database router. Assuming you have the correct environment variables and Python virtual environment, run:
|
||||
|
||||
@@ -247,7 +247,7 @@ cd src/backend
|
||||
uv run python manage.py migrate --database admin
|
||||
```
|
||||
|
||||
## Apply fixtures
|
||||
### Apply fixtures
|
||||
|
||||
Fixtures are used to populate the database with initial development data.
|
||||
|
||||
@@ -258,7 +258,7 @@ uv run python manage.py loaddata api/fixtures/0_dev_users.json --database admin
|
||||
|
||||
> The default credentials are `dev@prowler.com:Thisisapassword123@` or `dev2@prowler.com:Thisisapassword123@`
|
||||
|
||||
## Run tests
|
||||
### Run tests
|
||||
|
||||
Note that the tests will fail if you use the same `.env` file as the development environment.
|
||||
|
||||
@@ -269,7 +269,7 @@ cd src/backend
|
||||
uv run pytest
|
||||
```
|
||||
|
||||
# Custom commands
|
||||
## Custom commands
|
||||
|
||||
Django provides a way to create custom commands that can be run from the command line.
|
||||
|
||||
@@ -281,7 +281,7 @@ To run a custom command, you need to be in the `prowler/api/src/backend` directo
|
||||
uv run python manage.py <command_name>
|
||||
```
|
||||
|
||||
## Generate dummy data
|
||||
### Generate dummy data
|
||||
|
||||
```console
|
||||
python manage.py findings --tenant
|
||||
@@ -298,7 +298,7 @@ This command creates, for a given tenant, a provider, scan and a set of findings
|
||||
>
|
||||
> The last step is required to access the findings details, since the UI needs that to print all the information.
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
```console
|
||||
~/backend $ uv run python manage.py findings --tenant
|
||||
|
||||
+2
-2
@@ -134,7 +134,7 @@ Example 1 is vague and even potentially ambiguous. Verbs state your purpose and
|
||||
|
||||
Explicit use of second-person pronouns (you) and possessives (your) should be minimized whenever possible. Those constructions are best reserved for cases when instructions are directly given in an imperative form:
|
||||
|
||||
**Example of Improvement Through Avoiding Second Person Pronouns**
|
||||
### Example of Improvement Through Avoiding Second Person Pronouns
|
||||
|
||||
**Original:**
|
||||
Prowler App can be installed in different ways, depending on your environment:
|
||||
@@ -236,7 +236,7 @@ The use of bullet points is highly recommended when:
|
||||
* Information can be logically divided into multiple categories, each sharing characteristics, features, or other relevant classifications.
|
||||
* Items are significant enough as standalone concepts to deserve their own bullet point.
|
||||
|
||||
**Example of Improvement Through Bullet Points**
|
||||
#### Example of Improvement Through Bullet Points
|
||||
|
||||
**Original:**
|
||||
It contains hundreds of controls covering CIS, NIST 800, NIST CSF, CISA, RBI, FedRAMS, PCI-DSS, GDPR, HIPAA, FFIEC, SOC2, GXP, AWS Well-Architected Framework Security Pillar, AWS Foundational Technical Review (FTR), ENS (Spanish National Security Scheme), and your custom security frameworks.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> **Skills Reference**: See [`prowler-mcp`](../skills/prowler-mcp/SKILL.md)
|
||||
|
||||
### Auto-invoke Skills
|
||||
## Auto-invoke Skills
|
||||
|
||||
When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
|
||||
@@ -68,7 +68,7 @@ Python 3.12+ | FastMCP 2.13.1 | httpx (async) | Pydantic | uv
|
||||
|
||||
## PROJECT STRUCTURE
|
||||
|
||||
```
|
||||
```text
|
||||
mcp_server/prowler_mcp_server/
|
||||
├── server.py # Main orchestration
|
||||
├── prowler_hub/server.py # Hub tools (no auth)
|
||||
|
||||
@@ -83,14 +83,14 @@ npm install --save-exact mcp-remote@0.1.38
|
||||
|
||||
### 2. Local STDIO Mode
|
||||
|
||||
**Run the server locally on your machine**
|
||||
Run the server locally on your machine:
|
||||
|
||||
- Runs as a subprocess of your MCP client
|
||||
- Requires Python 3.12+ or Docker
|
||||
|
||||
### 3. Self-Hosted HTTP Mode
|
||||
|
||||
**Deploy your own remote MCP server**
|
||||
Deploy your own remote MCP server:
|
||||
|
||||
- Full control over deployment
|
||||
- Requires Python 3.12+ or Docker
|
||||
@@ -132,7 +132,7 @@ All tools follow a consistent naming pattern with prefixes:
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
```text
|
||||
prowler_mcp_server/
|
||||
├── server.py # Main orchestrator (imports sub-servers with prefixes)
|
||||
├── main.py # CLI entry point
|
||||
@@ -154,17 +154,20 @@ prowler_mcp_server/
|
||||
|
||||
The Prowler MCP Server enables powerful workflows through AI assistants:
|
||||
|
||||
**Security Operations**
|
||||
### Security Operations
|
||||
|
||||
- "Show me all critical findings from my AWS production accounts"
|
||||
- "Register my new AWS account in Prowler and run a scheduled scan every day"
|
||||
- "List all muted findings and detect what findgings are muted by a not enough good reason in relation to their severity"
|
||||
|
||||
**Security Research**
|
||||
### Security Research
|
||||
|
||||
- "Explain what the S3 bucket public access Prowler check does"
|
||||
- "Find all Prowler checks related to encryption at rest"
|
||||
- "What is the latest version of the CIS that Prowler is covering per provider?"
|
||||
|
||||
**Documentation & Learning**
|
||||
### Documentation & Learning
|
||||
|
||||
- "How do I configure Prowler to scan my GCP organization?"
|
||||
- "What authentication methods does Prowler support for Azure?"
|
||||
- "How can I contribute with a new security check to Prowler?"
|
||||
|
||||
@@ -28,12 +28,12 @@ This Terraform configuration creates the necessary IAM role and policies to allo
|
||||
|
||||
### Usage Examples
|
||||
|
||||
#### Basic deployment (without S3 integration):
|
||||
#### Basic deployment (without S3 integration)
|
||||
```bash
|
||||
terraform apply -var="external_id=your-external-id-here"
|
||||
```
|
||||
|
||||
#### With S3 integration enabled:
|
||||
#### With S3 integration enabled
|
||||
```bash
|
||||
terraform apply \
|
||||
-var="external_id=your-external-id-here" \
|
||||
@@ -42,14 +42,14 @@ terraform apply \
|
||||
-var="s3_integration_bucket_account_id=123456789012"
|
||||
```
|
||||
|
||||
#### Using terraform.tfvars file (Recommended):
|
||||
#### Using terraform.tfvars file (Recommended)
|
||||
```bash
|
||||
cp terraform.tfvars.example terraform.tfvars
|
||||
# Edit the file with your values
|
||||
terraform apply
|
||||
```
|
||||
|
||||
#### Command line variables (Alternative):
|
||||
#### Command line variables (Alternative)
|
||||
```bash
|
||||
terraform apply -var="external_id=your-external-id-here"
|
||||
```
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
> - [`prowler-compliance`](../skills/prowler-compliance/SKILL.md) - Compliance framework structure
|
||||
> - [`pytest`](../skills/pytest/SKILL.md) - Generic pytest patterns
|
||||
|
||||
### Auto-invoke Skills
|
||||
## Auto-invoke Skills
|
||||
|
||||
When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
|
||||
@@ -44,7 +44,7 @@ The Prowler SDK is the core Python engine powering cloud security assessments ac
|
||||
|
||||
### Provider Architecture
|
||||
|
||||
```
|
||||
```text
|
||||
prowler/providers/{provider}/
|
||||
├── {provider}_provider.py # Main provider class
|
||||
├── models.py # Provider-specific models
|
||||
@@ -91,7 +91,7 @@ Python 3.10+ | uv | pytest | moto (AWS mocking) | Pre-commit hooks (black, flake
|
||||
|
||||
## PROJECT STRUCTURE
|
||||
|
||||
```
|
||||
```text
|
||||
prowler/
|
||||
├── __main__.py # CLI entry point
|
||||
├── config/ # Global configuration
|
||||
|
||||
+3
-3
@@ -36,7 +36,7 @@ After running setup, restart your AI coding assistant to load the skills.
|
||||
|
||||
Skills are automatically discovered by the AI agent. To manually load a skill during a session:
|
||||
|
||||
```
|
||||
```text
|
||||
Read skills/{skill-name}/SKILL.md
|
||||
```
|
||||
|
||||
@@ -90,7 +90,7 @@ Patterns tailored for Prowler development:
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
```text
|
||||
skills/
|
||||
├── {skill-name}/
|
||||
│ ├── SKILL.md # Required - main instrunsction and metadata
|
||||
@@ -118,7 +118,7 @@ This reads `metadata.scope` and `metadata.auto_invoke` from each `SKILL.md` and
|
||||
|
||||
Use the `skill-creator` skill for guidance:
|
||||
|
||||
```
|
||||
```text
|
||||
Read skills/skill-creator/SKILL.md
|
||||
```
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ When implementing a new endpoint, review these patterns in order:
|
||||
## Decision Trees
|
||||
|
||||
### Which Serializer?
|
||||
```
|
||||
```text
|
||||
GET list/retrieve → <Model>Serializer
|
||||
POST create → <Model>CreateSerializer
|
||||
PATCH update → <Model>UpdateSerializer
|
||||
@@ -62,7 +62,7 @@ PATCH update → <Model>UpdateSerializer
|
||||
```
|
||||
|
||||
### Which Base Serializer?
|
||||
```
|
||||
```text
|
||||
Read-only serializer → BaseModelSerializerV1
|
||||
Create with tenant_id → RLSSerializer + BaseWriteSerializer (auto-injects tenant_id on create)
|
||||
Update with validation → BaseWriteSerializer (tenant_id already exists on object)
|
||||
@@ -70,14 +70,14 @@ Non-model data → BaseSerializerV1
|
||||
```
|
||||
|
||||
### Which Filter Base?
|
||||
```
|
||||
```text
|
||||
Direct FK to Provider → BaseProviderFilter
|
||||
FK via Scan → BaseScanProviderFilter
|
||||
No provider relation → FilterSet
|
||||
```
|
||||
|
||||
### Which Base ViewSet?
|
||||
```
|
||||
```text
|
||||
RLS-protected model → BaseRLSViewSet (most common)
|
||||
Tenant operations → BaseTenantViewset
|
||||
User operations → BaseUserViewset
|
||||
@@ -85,7 +85,7 @@ No RLS required → BaseViewSet (rare)
|
||||
```
|
||||
|
||||
### Resource Name Format?
|
||||
```
|
||||
```text
|
||||
Single word model → plural lowercase (Provider → providers)
|
||||
Multi-word model → plural lowercase kebab (ProviderGroup → provider-groups)
|
||||
Through/join model → parent-child pattern (UserRoleRelationship → user-roles)
|
||||
@@ -490,7 +490,7 @@ When implementing or debugging, query these libraries via `mcp_context7_query-do
|
||||
| **drf-spectacular** | `/tfranzel/drf-spectacular` | OpenAPI schema, `@extend_schema` |
|
||||
|
||||
**Example queries:**
|
||||
```
|
||||
```text
|
||||
mcp_context7_query-docs(libraryId="/websites/django-rest-framework", query="ViewSet get_queryset best practices")
|
||||
mcp_context7_query-docs(libraryId="/tfranzel/drf-spectacular", query="extend_schema examples for custom actions")
|
||||
mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_2", query="model constraints and indexes")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
## ViewSet Hierarchy
|
||||
|
||||
```
|
||||
```text
|
||||
BaseViewSet (minimal - no RLS/auth)
|
||||
│
|
||||
├── BaseRLSViewSet (+ tenant filtering, RLS-protected models)
|
||||
@@ -31,7 +31,7 @@ BaseViewSet (minimal - no RLS/auth)
|
||||
|
||||
## Serializer Hierarchy
|
||||
|
||||
```
|
||||
```text
|
||||
BaseModelSerializerV1 (JSON:API defaults, read_only_fields)
|
||||
│
|
||||
├── RLSSerializer (auto-injects tenant_id from request)
|
||||
@@ -47,7 +47,7 @@ BaseModelSerializerV1 (JSON:API defaults, read_only_fields)
|
||||
|
||||
## Filter Hierarchy
|
||||
|
||||
```
|
||||
```text
|
||||
FilterSet (django-filter)
|
||||
│
|
||||
├── CommonFindingFilters (mixin for date ranges, delta, status)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Content Type
|
||||
|
||||
```
|
||||
```http
|
||||
Content-Type: application/vnd.api+json
|
||||
Accept: application/vnd.api+json
|
||||
```
|
||||
|
||||
@@ -364,7 +364,7 @@ Batch utilities: `api/db_utils.py` (`batch_delete`, `create_objects_in_batches`,
|
||||
|
||||
## Decision tree
|
||||
|
||||
```
|
||||
```text
|
||||
Auto-generated migration?
|
||||
├── Yes → Split it following the rules below
|
||||
└── No → Review it against the rules below
|
||||
@@ -420,7 +420,7 @@ When implementing or debugging migration patterns, query these libraries via `mc
|
||||
| django-postgres-extra | `/SectorLabs/django-postgres-extra` | Partitioned models, `PostgresPartitionedModel`, partition management |
|
||||
|
||||
**Example queries:**
|
||||
```
|
||||
```text
|
||||
mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_1", query="migration operations AddIndex RunPython atomic")
|
||||
mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_1", query="database indexes Meta class concurrently")
|
||||
mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="CREATE INDEX CONCURRENTLY partitioned table")
|
||||
|
||||
@@ -30,7 +30,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch
|
||||
|
||||
## File Layout
|
||||
|
||||
```
|
||||
```text
|
||||
.github/
|
||||
├── workflows/
|
||||
│ ├── {name}.md # Frontmatter + thin context dispatcher
|
||||
@@ -308,7 +308,7 @@ After modifying any `.github/workflows/*.md`:
|
||||
|
||||
Add to repo root so lock files auto-resolve on merge:
|
||||
|
||||
```
|
||||
```text
|
||||
.github/workflows/*.lock.yml linguist-generated=true merge=ours
|
||||
```
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ This skill focuses on **spec compliance**. For **implementation patterns** (View
|
||||
|
||||
If Context7 MCP is available, query the JSON:API spec directly:
|
||||
|
||||
```
|
||||
```text
|
||||
mcp_context7_resolve-library-id(query="jsonapi specification")
|
||||
mcp_context7_query-docs(libraryId="<resolved-id>", query="[specific topic: relationships, errors, etc.]")
|
||||
```
|
||||
@@ -44,7 +44,7 @@ mcp_context7_query-docs(libraryId="<resolved-id>", query="[specific topic: relat
|
||||
|
||||
If Context7 is not available, fetch from the official spec:
|
||||
|
||||
```
|
||||
```text
|
||||
WebFetch(url="https://jsonapi.org/format/", prompt="Extract rules for [specific topic]")
|
||||
```
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## App Router File Conventions
|
||||
|
||||
```
|
||||
```text
|
||||
app/
|
||||
├── layout.tsx # Root layout (required)
|
||||
├── page.tsx # Home page (/)
|
||||
|
||||
@@ -36,7 +36,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
```text
|
||||
tests/
|
||||
├── base-page.ts # Parent class for ALL pages
|
||||
├── helpers.ts # Shared utilities
|
||||
@@ -182,14 +182,14 @@ export class SignUpPage extends BasePage {
|
||||
|
||||
## Refactoring Guidelines
|
||||
|
||||
### Move to `BasePage` when:
|
||||
### Move to `BasePage` when
|
||||
- ✅ Navigation helpers used by multiple pages (`waitForPageLoad()`, `getCurrentUrl()`)
|
||||
- ✅ Common UI interactions (notifications, modals, theme toggles)
|
||||
- ✅ Verification patterns repeated across pages (`isVisible()`, `waitForVisible()`)
|
||||
- ✅ Error handling that applies to all pages
|
||||
- ✅ Screenshot utilities for debugging
|
||||
|
||||
### Move to `helpers.ts` when:
|
||||
### Move to `helpers.ts` when
|
||||
- ✅ Test data generation (`generateUniqueEmail()`, `generateTestUser()`)
|
||||
- ✅ Setup/teardown utilities (`createTestUser()`, `cleanupTestData()`)
|
||||
- ✅ Custom assertions (`expectNotificationToContain()`)
|
||||
|
||||
@@ -225,7 +225,7 @@ Rebuild invalid indexes without locking writes:
|
||||
REINDEX INDEX CONCURRENTLY index_name;
|
||||
```
|
||||
|
||||
### Understanding _ccnew and _ccold artifacts
|
||||
### Understanding _ccnew and_ccold artifacts
|
||||
|
||||
When `CREATE INDEX CONCURRENTLY` or `REINDEX INDEX CONCURRENTLY` is interrupted, temporary indexes may remain:
|
||||
|
||||
@@ -377,7 +377,8 @@ VACUUM (ANALYZE) table_name;
|
||||
| PostgreSQL | `/websites/postgresql_org_docs_current` | Index types, EXPLAIN, partitioned table indexing, REINDEX |
|
||||
|
||||
**Example queries:**
|
||||
```
|
||||
|
||||
```text
|
||||
mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="CREATE INDEX CONCURRENTLY partitioned table")
|
||||
mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="EXPLAIN ANALYZE BUFFERS query plan")
|
||||
mcp_context7_query-docs(libraryId="/websites/postgresql_org_docs_current", query="partial index WHERE clause")
|
||||
|
||||
@@ -61,7 +61,7 @@ Provider.objects.filter(connected=True) # Requires rls_transaction context
|
||||
|
||||
### RLS Transaction Flow
|
||||
|
||||
```
|
||||
```text
|
||||
Request → Authentication → BaseRLSViewSet.initial()
|
||||
│
|
||||
├─ Extract tenant_id from JWT
|
||||
@@ -92,7 +92,7 @@ When implementing Prowler-specific API features:
|
||||
## Decision Trees
|
||||
|
||||
### Which Base Model?
|
||||
```
|
||||
```text
|
||||
Tenant-scoped data → RowLevelSecurityProtectedModel
|
||||
Global/shared data → models.Model + BaseSecurityConstraint (rare)
|
||||
Partitioned time-series → PostgresPartitionedModel + RowLevelSecurityProtectedModel
|
||||
@@ -100,14 +100,14 @@ Soft-deletable → Add is_deleted + ActiveProviderManager
|
||||
```
|
||||
|
||||
### Which Manager?
|
||||
```
|
||||
```text
|
||||
Normal queries → Model.objects (excludes deleted)
|
||||
Include deleted records → Model.all_objects
|
||||
Celery task context → Must use rls_transaction() first
|
||||
```
|
||||
|
||||
### Which Database?
|
||||
```
|
||||
```text
|
||||
Standard API queries → default (automatic via ViewSet)
|
||||
Read-only operations → replica (automatic for GET in BaseRLSViewSet)
|
||||
Auth/admin operations → MainRouter.admin_db
|
||||
@@ -115,7 +115,7 @@ Cross-tenant lookups → MainRouter.admin_db (use sparingly!)
|
||||
```
|
||||
|
||||
### Celery Task Decorator Order?
|
||||
```
|
||||
```python
|
||||
@shared_task(base=RLSTask, name="...", queue="...")
|
||||
@set_tenant # First: sets tenant context
|
||||
@handle_provider_deletion # Second: handles deleted providers
|
||||
@@ -496,7 +496,7 @@ When implementing or debugging Prowler-specific patterns, query these libraries
|
||||
| **Django** | `/websites/djangoproject_en_5_2` | Models, ORM, constraints, indexes |
|
||||
|
||||
**Example queries:**
|
||||
```
|
||||
```text
|
||||
mcp_context7_query-docs(libraryId="/websites/celeryq_dev_en_stable", query="shared_task decorator retry patterns")
|
||||
mcp_context7_query-docs(libraryId="/celery/django-celery-beat", query="periodic task database scheduler")
|
||||
mcp_context7_query-docs(libraryId="/websites/djangoproject_en_5_2", query="model constraints CheckConstraint UniqueConstraint")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Settings File Structure
|
||||
|
||||
```
|
||||
```text
|
||||
api/src/backend/config/
|
||||
├── django/
|
||||
│ ├── base.py # Base settings (all environments)
|
||||
|
||||
@@ -247,7 +247,7 @@ class JSONAPIMeta:
|
||||
|
||||
## Decision Tree: New Model
|
||||
|
||||
```
|
||||
```text
|
||||
Is it tenant-scoped data?
|
||||
├── Yes → Inherit RowLevelSecurityProtectedModel
|
||||
│ Add RowLevelSecurityConstraint
|
||||
|
||||
@@ -228,7 +228,7 @@ AWS_QUERIES: list[AttackPathsQueryDefinition] = [
|
||||
|
||||
**FIRST**, read all files in the queries module to understand the structure, type definitions, registration, and existing style:
|
||||
|
||||
```
|
||||
```text
|
||||
api/src/backend/api/attack_paths/queries/
|
||||
├── __init__.py # Module exports
|
||||
├── types.py # AttackPathsQueryDefinition, AttackPathsQueryParameterDefinition
|
||||
@@ -250,7 +250,7 @@ grep cartography api/pyproject.toml
|
||||
|
||||
Build the schema URL (ALWAYS use the specific tag, not master/main):
|
||||
|
||||
```
|
||||
```text
|
||||
# Git dependency (prowler-cloud/cartography@0.126.1):
|
||||
https://raw.githubusercontent.com/prowler-cloud/cartography/refs/tags/0.126.1/docs/root/modules/{provider}/schema.md
|
||||
|
||||
@@ -283,7 +283,7 @@ Add the constant to the `{PROVIDER}_QUERIES` list.
|
||||
|
||||
### Query ID
|
||||
|
||||
```
|
||||
```text
|
||||
{provider}-{category}-{description}
|
||||
```
|
||||
|
||||
@@ -291,7 +291,7 @@ Examples: `aws-ec2-privesc-passrole-iam`, `aws-ec2-instances-internet-exposed`
|
||||
|
||||
### Query constant name
|
||||
|
||||
```
|
||||
```text
|
||||
{PROVIDER}_{CATEGORY}_{DESCRIPTION}
|
||||
```
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ metadata:
|
||||
|
||||
## Commit Format
|
||||
|
||||
```
|
||||
```text
|
||||
type(scope): concise description
|
||||
|
||||
- Key change 1
|
||||
@@ -68,7 +68,7 @@ type(scope): concise description
|
||||
|
||||
### Title Line
|
||||
|
||||
```
|
||||
```text
|
||||
# GOOD - Concise and clear
|
||||
feat(api): add provider connection retry logic
|
||||
fix(ui): resolve dashboard loading state
|
||||
@@ -83,7 +83,7 @@ fix(ui): fix the bug in dashboard component on line 45
|
||||
|
||||
### Body (Bullet Points)
|
||||
|
||||
```
|
||||
```text
|
||||
# GOOD - High-level changes
|
||||
- Add retry mechanism for failed connections
|
||||
- Document task composition patterns
|
||||
@@ -132,7 +132,7 @@ fix(ui): fix the bug in dashboard component on line 45
|
||||
|
||||
## Decision Tree
|
||||
|
||||
```
|
||||
```text
|
||||
Single file changed?
|
||||
├─ Yes → May omit body, title only
|
||||
└─ No → Include body with key changes
|
||||
|
||||
@@ -53,7 +53,7 @@ diff dashboard/compliance/{new_framework}.py \
|
||||
|
||||
## Decision Tree
|
||||
|
||||
```
|
||||
```text
|
||||
JSON Valid?
|
||||
├── No → FAIL: Fix JSON syntax errors
|
||||
└── Yes ↓
|
||||
|
||||
@@ -59,7 +59,7 @@ See "Compliance Framework Location" and "Framework-Specific Attribute Structures
|
||||
|
||||
**Every framework directory follows this exact convention** — do not deviate:
|
||||
|
||||
```
|
||||
```text
|
||||
{framework}/
|
||||
├── __init__.py
|
||||
├── {framework}.py # ONLY get_{framework}_table() — NO function docstring
|
||||
@@ -85,7 +85,7 @@ See "Compliance Framework Location" and "Framework-Specific Attribute Structures
|
||||
|
||||
### The CLI Pipeline (end-to-end)
|
||||
|
||||
```
|
||||
```text
|
||||
prowler aws --compliance ccc_aws
|
||||
↓
|
||||
Compliance.get_bulk("aws") → parses prowler/compliance/aws/*.json
|
||||
@@ -483,6 +483,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler
|
||||
## Available Compliance Frameworks
|
||||
|
||||
### AWS (41 frameworks)
|
||||
|
||||
| Framework | File Name |
|
||||
|-----------|-----------|
|
||||
| CIS 1.4, 1.5, 2.0, 3.0, 4.0, 5.0 | `cis_{version}_aws.json` |
|
||||
@@ -508,6 +509,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler
|
||||
| NIS2 | `nis2_aws.json` |
|
||||
|
||||
### Azure (15+ frameworks)
|
||||
|
||||
| Framework | File Name |
|
||||
|-----------|-----------|
|
||||
| CIS 2.0, 2.1, 3.0, 4.0 | `cis_{version}_azure.json` |
|
||||
@@ -518,6 +520,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler
|
||||
| NIST CSF 2.0 | `nist_csf_2.0_azure.json` |
|
||||
|
||||
### GCP (15+ frameworks)
|
||||
|
||||
| Framework | File Name |
|
||||
|-----------|-----------|
|
||||
| CIS 2.0, 3.0, 4.0 | `cis_{version}_gcp.json` |
|
||||
@@ -528,6 +531,7 @@ Prowler ThreatScore is a custom security scoring framework developed by Prowler
|
||||
| NIST CSF 2.0 | `nist_csf_2.0_gcp.json` |
|
||||
|
||||
### Kubernetes (6 frameworks)
|
||||
|
||||
| Framework | File Name |
|
||||
|-----------|-----------|
|
||||
| CIS 1.8, 1.10, 1.11 | `cis_{version}_kubernetes.json` |
|
||||
@@ -561,7 +565,7 @@ done
|
||||
|
||||
The sync tooling is split into three layers so adding a new framework only takes a YAML config (and optionally a new parser module for an unfamiliar upstream format):
|
||||
|
||||
```
|
||||
```text
|
||||
skills/prowler-compliance/assets/
|
||||
├── sync_framework.py # generic runner — works for any framework
|
||||
├── configs/
|
||||
@@ -902,7 +906,7 @@ Add fixtures to `tests/lib/outputs/compliance/fixtures.py`: one `Compliance` obj
|
||||
|
||||
**The table dispatcher file (`{framework}.py`) MUST NOT import `Finding`** (directly or transitively). The cycle is:
|
||||
|
||||
```
|
||||
```text
|
||||
compliance.compliance imports get_{framework}_table
|
||||
→ {framework}.py imports ComplianceOutput
|
||||
→ compliance_output imports Finding
|
||||
|
||||
@@ -46,7 +46,7 @@ Each framework type has a specific Pydantic model in `compliance_models.py`:
|
||||
|
||||
## File Naming Convention
|
||||
|
||||
```
|
||||
```text
|
||||
{framework}_{version}_{provider}.json
|
||||
```
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ Reference without articles:
|
||||
|
||||
## Documentation Structure
|
||||
|
||||
```
|
||||
```text
|
||||
docs/
|
||||
├── getting-started/
|
||||
├── tutorials/
|
||||
|
||||
@@ -25,7 +25,7 @@ Use this skill when:
|
||||
|
||||
Every provider MUST follow this structure:
|
||||
|
||||
```
|
||||
```text
|
||||
prowler/providers/{provider}/
|
||||
├── __init__.py
|
||||
├── {provider}_provider.py # Main provider class
|
||||
|
||||
@@ -34,7 +34,7 @@ python3 prowler-cli.py <provider> --list-<metric>
|
||||
|
||||
The CLI output ends with a summary line like:
|
||||
|
||||
```
|
||||
```text
|
||||
There are 572 available checks.
|
||||
There is 1 available Compliance Framework.
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## Check Structure
|
||||
|
||||
```
|
||||
```text
|
||||
prowler/providers/{provider}/services/{service}/{check_name}/
|
||||
├── __init__.py
|
||||
├── {check_name}.py
|
||||
@@ -90,7 +90,7 @@ See `prowler-test-sdk` skill for test patterns (PASS, FAIL, no resources, error
|
||||
|
||||
## Check Naming Convention
|
||||
|
||||
```
|
||||
```text
|
||||
{service}_{resource}_{security_control}
|
||||
```
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## 1. Fixture Dependency Chain
|
||||
|
||||
```
|
||||
```text
|
||||
create_test_user (session) ─► tenants_fixture (function) ─► authenticated_client
|
||||
│
|
||||
└─► providers_fixture ─► scans_fixture ─► findings_fixture
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
## Fixture Dependency Graph
|
||||
|
||||
```
|
||||
```text
|
||||
create_test_user (session)
|
||||
│
|
||||
└─► tenants_fixture (function)
|
||||
|
||||
@@ -265,7 +265,7 @@ from tests.providers.kubernetes.kubernetes_fixtures import set_mocked_kubernetes
|
||||
|
||||
## Test File Structure
|
||||
|
||||
```
|
||||
```text
|
||||
tests/providers/{provider}/services/{service}/
|
||||
├── {service}_service_test.py # Service tests
|
||||
└── {check_name}/
|
||||
|
||||
@@ -19,7 +19,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## Prowler UI Test Structure
|
||||
|
||||
```
|
||||
```text
|
||||
ui/tests/
|
||||
├── base-page.ts # Prowler-specific base page
|
||||
├── helpers.ts # Prowler test utilities
|
||||
@@ -35,13 +35,13 @@ ui/tests/
|
||||
|
||||
**⚠️ ALWAYS verify BEFORE completing any E2E task:**
|
||||
|
||||
### When CREATING new tests:
|
||||
### When CREATING new tests
|
||||
- [ ] `{page-name}-page.ts` - Page Object created/updated
|
||||
- [ ] `{page-name}.spec.ts` - Tests added with correct tags (@TEST-ID)
|
||||
- [ ] `{page-name}.md` - Documentation created with ALL test cases
|
||||
- [ ] Test IDs in `.md` match tags in `.spec.ts`
|
||||
|
||||
### When MODIFYING existing tests:
|
||||
### When MODIFYING existing tests
|
||||
- [ ] `{page-name}.md` MUST be updated if:
|
||||
- Test cases were added/removed
|
||||
- Test flow changed (steps)
|
||||
@@ -49,7 +49,7 @@ ui/tests/
|
||||
- Tags or priorities changed
|
||||
- [ ] Test IDs synchronized between `.md` and `.spec.ts`
|
||||
|
||||
### Quick validation:
|
||||
### Quick validation
|
||||
```bash
|
||||
# Verify .md exists for each test folder
|
||||
ls ui/tests/{feature}/{feature}.md
|
||||
@@ -59,7 +59,8 @@ grep -o "@[A-Z]*-E2E-[0-9]*" ui/tests/{feature}/{feature}.spec.ts | sort -u
|
||||
grep -o "\`[A-Z]*-E2E-[0-9]*\`" ui/tests/{feature}/{feature}.md | sort -u
|
||||
```
|
||||
|
||||
**❌ An E2E change is NOT considered complete without updating the corresponding .md file**
|
||||
> [!IMPORTANT]
|
||||
> ❌ An E2E change is NOT considered complete without updating the corresponding `.md` file.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## Tech Stack (Versions)
|
||||
|
||||
```
|
||||
```text
|
||||
Next.js 16.2.3 | React 19.2.5 | Tailwind 4.1.18 | shadcn/ui
|
||||
Zod 4.1.11 | React Hook Form 7.62.0 | Zustand 5.0.8
|
||||
NextAuth 5.0.0-beta.30 | Recharts 2.15.4
|
||||
@@ -43,7 +43,7 @@ HeroUI 2.8.4 (LEGACY - do not add new components)
|
||||
|
||||
### Component Placement
|
||||
|
||||
```
|
||||
```text
|
||||
New feature UI? → shadcn/ui + Tailwind
|
||||
Existing HeroUI feature? → Keep HeroUI (don't mix)
|
||||
Used 1 feature? → features/{feature}/components/
|
||||
@@ -54,7 +54,7 @@ Server component? → No directive needed
|
||||
|
||||
### Code Location
|
||||
|
||||
```
|
||||
```text
|
||||
Server action → actions/{feature}/{feature}.ts
|
||||
Data transform → actions/{feature}/{feature}.adapter.ts
|
||||
Types (shared 2+) → types/{domain}.ts
|
||||
@@ -69,7 +69,7 @@ HeroUI components → components/ui/ (LEGACY)
|
||||
|
||||
### Styling Decision
|
||||
|
||||
```
|
||||
```text
|
||||
Tailwind class exists? → className
|
||||
Dynamic value? → style prop
|
||||
Conditional styles? → cn()
|
||||
@@ -85,7 +85,7 @@ Recharts/library? → CHART_COLORS constant + var()
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
```text
|
||||
ui/
|
||||
├── app/
|
||||
│ ├── (auth)/ # Auth pages (login, signup)
|
||||
|
||||
@@ -29,7 +29,7 @@ Create a skill when:
|
||||
|
||||
## Skill Structure
|
||||
|
||||
```
|
||||
```text
|
||||
skills/{skill-name}/
|
||||
├── SKILL.md # Required - main skill file
|
||||
├── assets/ # Optional - templates, schemas, examples
|
||||
@@ -43,7 +43,7 @@ skills/{skill-name}/
|
||||
|
||||
## SKILL.md Template
|
||||
|
||||
```markdown
|
||||
````markdown
|
||||
---
|
||||
name: {skill-name}
|
||||
description: >
|
||||
@@ -77,7 +77,7 @@ metadata:
|
||||
|
||||
- **Templates**: See [assets/](assets/) for {description}
|
||||
- **Documentation**: See [references/](references/) for local docs
|
||||
```
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
@@ -94,7 +94,7 @@ metadata:
|
||||
|
||||
## Decision: assets/ vs references/
|
||||
|
||||
```
|
||||
```text
|
||||
Need code templates? → assets/
|
||||
Need JSON schemas? → assets/
|
||||
Need example configs? → assets/
|
||||
@@ -108,7 +108,7 @@ Link to external guides? → references/ (with local path)
|
||||
|
||||
## Decision: Prowler-Specific vs Generic
|
||||
|
||||
```
|
||||
```text
|
||||
Patterns apply to ANY project? → Generic skill (e.g., pytest, typescript)
|
||||
Patterns are Prowler-specific? → prowler-{name} skill
|
||||
Generic skill needs Prowler info? → Add references/ pointing to Prowler docs
|
||||
|
||||
@@ -38,7 +38,7 @@ Use this skill when:
|
||||
|
||||
## Decision Tree
|
||||
|
||||
```
|
||||
```text
|
||||
{Question 1}? → {Action A}
|
||||
{Question 2}? → {Action B}
|
||||
Otherwise → {Default action}
|
||||
|
||||
@@ -14,7 +14,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
|
||||
|
||||
## Styling Decision Tree
|
||||
|
||||
```
|
||||
```text
|
||||
Tailwind class exists? → className="..."
|
||||
Dynamic value? → style={{ width: `${x}%` }}
|
||||
Conditional styles? → cn("base", condition && "variant")
|
||||
|
||||
+12
-12
@@ -20,7 +20,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, Task
|
||||
|
||||
## TDD Cycle (MANDATORY)
|
||||
|
||||
```
|
||||
```text
|
||||
+-----------------------------------------+
|
||||
| RED -> GREEN -> REFACTOR |
|
||||
| ^ | |
|
||||
@@ -28,7 +28,7 @@ allowed-tools: Read, Edit, Write, Glob, Grep, Bash, Task
|
||||
+-----------------------------------------+
|
||||
```
|
||||
|
||||
**The question is NOT "should I write tests?" but "what tests do I need?"**
|
||||
The question is NOT "should I write tests?" but "what tests do I need?"
|
||||
|
||||
---
|
||||
|
||||
@@ -94,7 +94,7 @@ uv run pytest api/src/backend/api/tests/test_models.py -v
|
||||
|
||||
### Decision Tree (All Stacks)
|
||||
|
||||
```
|
||||
```text
|
||||
+------------------------------------------+
|
||||
| Does test file exist for this code? |
|
||||
+----------+-----------------------+-------+
|
||||
@@ -122,7 +122,7 @@ uv run pytest api/src/backend/api/tests/test_models.py -v
|
||||
|
||||
### For NEW Functionality
|
||||
|
||||
**UI (Vitest)**
|
||||
#### UI (Vitest)
|
||||
|
||||
```typescript
|
||||
describe("PriceCalculator", () => {
|
||||
@@ -139,7 +139,7 @@ describe("PriceCalculator", () => {
|
||||
});
|
||||
```
|
||||
|
||||
**SDK (pytest)**
|
||||
#### SDK (pytest)
|
||||
|
||||
```python
|
||||
class Test_ec2_ami_public:
|
||||
@@ -159,7 +159,7 @@ class Test_ec2_ami_public:
|
||||
assert len(result) == 0
|
||||
```
|
||||
|
||||
**API (pytest-django)**
|
||||
#### API (pytest-django)
|
||||
|
||||
```python
|
||||
@pytest.mark.django_db
|
||||
@@ -192,18 +192,18 @@ Write a test that **reproduces the bug** first:
|
||||
|
||||
**API:** `assert response.status_code == 403 # Currently returns 200`
|
||||
|
||||
**Run -> Should FAIL (reproducing the bug)**
|
||||
Run -> Should FAIL (reproducing the bug).
|
||||
|
||||
### For REFACTORING
|
||||
|
||||
Capture ALL current behavior BEFORE refactoring:
|
||||
|
||||
```
|
||||
```text
|
||||
# Any stack: run ALL existing tests, they should PASS
|
||||
# This is your safety net - if any fail after refactoring, you broke something
|
||||
```
|
||||
|
||||
**Run -> All should PASS (baseline)**
|
||||
Run -> All should PASS (baseline).
|
||||
|
||||
---
|
||||
|
||||
@@ -288,13 +288,13 @@ Tests GREEN -> Improve code quality WITHOUT changing behavior.
|
||||
- Add types/validation
|
||||
- Reduce duplication
|
||||
|
||||
**Run tests after EACH change -> Must stay GREEN**
|
||||
Run tests after EACH change -> Must stay GREEN.
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
```
|
||||
```text
|
||||
+------------------------------------------------+
|
||||
| TDD WORKFLOW |
|
||||
+------------------------------------------------+
|
||||
@@ -320,7 +320,7 @@ Tests GREEN -> Improve code quality WITHOUT changing behavior.
|
||||
|
||||
## Anti-Patterns (NEVER DO)
|
||||
|
||||
```
|
||||
```python
|
||||
# ANY language:
|
||||
|
||||
# 1. Code first, tests after
|
||||
|
||||
@@ -181,7 +181,7 @@ expect(screen.getByRole("button")).toBeDisabled();
|
||||
|
||||
## File Organization
|
||||
|
||||
```
|
||||
```text
|
||||
components/
|
||||
├── Button/
|
||||
│ ├── Button.tsx
|
||||
|
||||
+4
-4
@@ -15,7 +15,7 @@
|
||||
> - [`vitest`](../skills/vitest/SKILL.md) - Unit testing with React Testing Library
|
||||
> - [`tdd`](../skills/tdd/SKILL.md) - TDD workflow (MANDATORY for UI tasks)
|
||||
|
||||
### Auto-invoke Skills
|
||||
## Auto-invoke Skills
|
||||
|
||||
When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
|
||||
@@ -89,7 +89,7 @@ When performing these actions, ALWAYS invoke the corresponding skill FIRST:
|
||||
|
||||
### Component Placement
|
||||
|
||||
```
|
||||
```text
|
||||
New/Existing UI? → shadcn/ui + Tailwind (NEVER HeroUI for new code)
|
||||
Used 1 feature? → features/{feature}/components | Used 2+? → components/{domain}/
|
||||
Needs state/hooks? → "use client" | Server component? → No directive
|
||||
@@ -97,7 +97,7 @@ Needs state/hooks? → "use client" | Server component? → No directive
|
||||
|
||||
### Code Location
|
||||
|
||||
```
|
||||
```text
|
||||
Server action → actions/{feature}/{feature}.ts
|
||||
Data transform → actions/{feature}/{feature}.adapter.ts
|
||||
Types (shared 2+) → types/{domain}.ts | Types (local 1) → {feature}/types.ts
|
||||
@@ -193,7 +193,7 @@ Zod 4.1.11 | React Hook Form 7.62.0 | Zustand 5.0.8 | NextAuth 5.0.0-beta.30 | R
|
||||
|
||||
## PROJECT STRUCTURE
|
||||
|
||||
```
|
||||
```text
|
||||
ui/
|
||||
├── app/(auth)/ # Auth pages
|
||||
├── app/(prowler)/ # Main app: compliance, findings, providers, scans
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory contains all shadcn/ui based components for the Prowler applicati
|
||||
|
||||
Example of a custom component:
|
||||
|
||||
```
|
||||
```text
|
||||
shadcn/
|
||||
├── card/
|
||||
│ ├── base-card/
|
||||
|
||||
+18
-18
@@ -21,7 +21,7 @@
|
||||
- Application is running.
|
||||
- No active session (cookies cleared).
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Clear all cookies.
|
||||
2. Navigate to /sign-in.
|
||||
@@ -29,7 +29,7 @@
|
||||
4. Navigate to /sign-up.
|
||||
5. Verify page loads.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Public routes are accessible without authentication.
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Navigate to a protected route.
|
||||
@@ -58,7 +58,7 @@
|
||||
4. Navigate to another protected route.
|
||||
5. Verify redirect to sign-in.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Invalid session results in redirect to sign-in.
|
||||
|
||||
@@ -79,13 +79,13 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to /sign-in with error=RefreshAccessTokenError query parameter.
|
||||
2. Check for toast notification.
|
||||
3. Verify form elements are still visible.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Toast shows "Session Expired" message with "Please sign in again".
|
||||
- Sign-in form is displayed and functional.
|
||||
@@ -107,13 +107,13 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to /sign-in with error=MissingRefreshToken query parameter.
|
||||
2. Check for toast notification.
|
||||
3. Verify email input is visible.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Toast shows "Session Error" message.
|
||||
- Sign-in form is displayed.
|
||||
@@ -135,12 +135,12 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to /sign-in with error=UnknownError query parameter.
|
||||
2. Check for toast notification.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Toast shows "Authentication Error" message with "Please sign in again".
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
- Application is running.
|
||||
- Valid test user credentials.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Navigate to a protected route (/scans).
|
||||
@@ -171,7 +171,7 @@
|
||||
5. Navigate to another protected route (/providers) using fresh navigation.
|
||||
6. Verify redirect to sign-in includes callbackUrl parameter.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- URL contains callbackUrl=/providers parameter.
|
||||
- User can sign in and be redirected back to the original destination.
|
||||
@@ -194,7 +194,7 @@
|
||||
- Application is running.
|
||||
- Valid test user credentials.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Verify home page is loaded.
|
||||
@@ -202,7 +202,7 @@
|
||||
4. Reload the page.
|
||||
5. Verify session is still valid with same user data.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Session persists after reload.
|
||||
- User email, userId, and tenantId remain the same.
|
||||
@@ -225,14 +225,14 @@
|
||||
- Application is running.
|
||||
- Valid test user credentials.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Capture initial session with permissions.
|
||||
3. Reload the page.
|
||||
4. Verify permissions match initial session.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- User permissions are identical before and after refresh.
|
||||
- User profile data (email, name, companyName) is preserved.
|
||||
@@ -255,14 +255,14 @@
|
||||
- Application is running.
|
||||
- Valid test user credentials.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Verify session is valid.
|
||||
3. Clear all cookies.
|
||||
4. Check session status.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Session returns null after cookies are cleared.
|
||||
- User is effectively logged out.
|
||||
|
||||
@@ -24,7 +24,7 @@ redirects to `/sign-in` with a `callbackUrl` that preserves the invitation token
|
||||
- Application is running.
|
||||
- No active session (cookies cleared).
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Clear all cookies.
|
||||
2. Navigate to `/invitation/accept?invitation_token=test-token`.
|
||||
@@ -32,7 +32,7 @@ redirects to `/sign-in` with a `callbackUrl` that preserves the invitation token
|
||||
4. Click the "I have an account — Sign in" button.
|
||||
5. Verify the redirect target and `callbackUrl` query param.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Heading "You've Been Invited" is visible.
|
||||
- Description text "invited to join a tenant" is visible.
|
||||
@@ -41,7 +41,7 @@ redirects to `/sign-in` with a `callbackUrl` that preserves the invitation token
|
||||
- Decoded `callbackUrl` equals `/invitation/accept?invitation_token=test-token`.
|
||||
- Decoded `callbackUrl` contains `invitation_token=test-token`.
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- `callbackUrl` preserves the original invitation path with token.
|
||||
|
||||
@@ -65,7 +65,7 @@ form actually renders (no redirect loop back to `/invitation/accept`).
|
||||
- Application is running.
|
||||
- No active session (cookies cleared).
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Clear all cookies.
|
||||
2. Navigate to `/invitation/accept?invitation_token=test-token`.
|
||||
@@ -73,17 +73,17 @@ form actually renders (no redirect loop back to `/invitation/accept`).
|
||||
4. Click the button.
|
||||
5. Verify the resulting URL and that the sign-up form is rendered.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- URL pathname is `/sign-up`.
|
||||
- Query param `invitation_token` equals `test-token`.
|
||||
- Sign-up form is rendered (email input and submit button visible).
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- No redirect back to `/invitation/accept` (smart router does not loop).
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- The legacy `action=signup` param is no longer emitted: the backward-compat
|
||||
redirect from `/sign-up?invitation_token=...` to `/invitation/accept` was
|
||||
@@ -111,7 +111,7 @@ that the "Go to Sign In" link redirects to `/sign-in`.
|
||||
- Application is running.
|
||||
- No active session (cookies cleared).
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Clear all cookies.
|
||||
2. Navigate to `/invitation/accept` (no query params).
|
||||
@@ -119,13 +119,13 @@ that the "Go to Sign In" link redirects to `/sign-in`.
|
||||
4. Click the "Go to Sign In" link.
|
||||
5. Verify redirect to `/sign-in`.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Heading "Invalid Invitation Link" is visible.
|
||||
- Description "No invitation token was provided" is visible.
|
||||
- "Go to Sign In" link is visible and clickable.
|
||||
- After click, URL matches `/sign-in`.
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Client-side render only: no API calls involved.
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
- `E2E_ORGANIZATION_ID` (expected organization for membership verification)
|
||||
- Application running with accessible UI/API endpoints
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to invitations page
|
||||
2. Click "Send Invitation" button
|
||||
@@ -40,7 +40,7 @@
|
||||
11. Verify successful login
|
||||
12. Navigate to user profile and verify `organizationId` matches `E2E_ORGANIZATION_ID`
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Invitation is created and a valid share URL is provided
|
||||
- Invited user can sign up successfully using the invitation link
|
||||
@@ -48,7 +48,7 @@
|
||||
- Login succeeds with the new credentials
|
||||
- User profile shows membership in the expected organization
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Invitations page loads and displays the heading
|
||||
- Send Invitation form is visible (email + role select)
|
||||
@@ -58,7 +58,7 @@
|
||||
- Login with the new account succeeds
|
||||
- Profile page shows the expected organization id
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses a fresh browser context for the invitee to avoid admin session leakage
|
||||
- Email should be unique per run (the test uses a random suffix)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
- Remove any existing provider with the same Account ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -36,14 +36,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- AWS provider successfully added with static credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays AWS option
|
||||
@@ -53,7 +53,7 @@
|
||||
- Provider exists in Scans table (verified by account ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for AWS credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -80,7 +80,7 @@
|
||||
- Remove any existing provider with the same Account ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -92,14 +92,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- AWS provider successfully added with role credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays AWS option
|
||||
@@ -109,7 +109,7 @@
|
||||
- Provider exists in Scans table (verified by account ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for AWS credentials and role ARN
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -137,7 +137,7 @@
|
||||
- Remove any existing provider with the same Subscription ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Subscription ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -148,14 +148,14 @@
|
||||
7. Verify redirect to Scans page
|
||||
8. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Azure provider successfully added with static credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays Azure option
|
||||
@@ -165,7 +165,7 @@
|
||||
- Provider exists in Scans table (verified by subscription ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for Azure credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -193,7 +193,7 @@
|
||||
- Remove any existing provider with the same Domain ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Domain ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -205,14 +205,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- M365 provider successfully added with static credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays M365 option
|
||||
@@ -222,7 +222,7 @@
|
||||
- Provider exists in Scans table (verified by domain ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for M365 credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -250,7 +250,7 @@
|
||||
- Remove any existing provider with the same Domain ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Domain ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -262,14 +262,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- M365 provider successfully added with certificate credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays M365 option
|
||||
@@ -279,7 +279,7 @@
|
||||
- Provider exists in Scans table (verified by domain ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for M365 certificate credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -308,7 +308,7 @@
|
||||
- Remove any existing provider with the same Context before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Context not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -320,14 +320,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Kubernetes provider successfully added with kubeconfig content
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays Kubernetes option
|
||||
@@ -339,7 +339,7 @@
|
||||
- Provider exists in Scans table (verified by context)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for Kubernetes context and kubeconfig file path
|
||||
- Kubeconfig content is read from file and used for authentication
|
||||
@@ -369,7 +369,7 @@
|
||||
- Remove any existing provider with the same Project ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Project ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -381,14 +381,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- GCP provider successfully added with service account key
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays GCP option
|
||||
@@ -400,7 +400,7 @@
|
||||
- Provider exists in Scans table (verified by project ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for GCP project ID and service account key
|
||||
- Service account key is provided as base64 encoded JSON content
|
||||
@@ -431,7 +431,7 @@
|
||||
- Remove any existing provider with the same Username before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Username not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -443,14 +443,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- GitHub provider successfully added with personal access token
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays GitHub option
|
||||
@@ -462,7 +462,7 @@
|
||||
- Provider exists in Scans table (verified by username)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for GitHub username and personal access token
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -491,7 +491,7 @@
|
||||
- Remove any existing provider with the same Username before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Username not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -503,14 +503,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- GitHub provider successfully added with GitHub App credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays GitHub option
|
||||
@@ -522,7 +522,7 @@
|
||||
- Provider exists in Scans table (verified by username)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for GitHub username, App ID, and base64 encoded private key
|
||||
- Private key is base64 encoded and must be decoded before use
|
||||
@@ -552,7 +552,7 @@
|
||||
- Remove any existing provider with the same Organization name before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Organization name not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -564,14 +564,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- GitHub provider successfully added with organization personal access token
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays GitHub option
|
||||
@@ -583,7 +583,7 @@
|
||||
- Provider exists in Scans table (verified by organization name)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for GitHub organization name and organization access token
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -612,7 +612,7 @@
|
||||
- Remove any existing provider with the same Account ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -625,14 +625,14 @@
|
||||
9. Verify redirect to Scans page
|
||||
10. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- AWS provider successfully added using AWS SDK default credentials to assume the role
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays AWS option
|
||||
@@ -643,7 +643,7 @@
|
||||
- Provider exists in Scans table (verified by account ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test leverages AWS SDK default credential chain (environment-configured keys) for Access Key and Secret Key
|
||||
- Environment variable `E2E_AWS_PROVIDER_ROLE_ARN` must reference a valid assumable role
|
||||
@@ -671,7 +671,7 @@
|
||||
- Remove any existing provider with the same Tenancy ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Tenancy ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -683,14 +683,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- OCI provider successfully added with API Key credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays OCI option
|
||||
@@ -702,7 +702,7 @@
|
||||
- Provider exists in Scans table (verified by tenancy ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for OCI credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -730,7 +730,7 @@
|
||||
- An OCI provider with the specified Tenancy ID must already exist (run PROVIDER-E2E-012 first)
|
||||
- This test must be run serially and never in parallel with other tests
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Verify OCI provider exists in the table
|
||||
@@ -742,7 +742,7 @@
|
||||
8. Click Next to submit
|
||||
9. Verify successful navigation to test connection page
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Update credentials page loads successfully
|
||||
- OCI credentials form is displayed with all required fields
|
||||
@@ -750,7 +750,7 @@
|
||||
- Credentials can be updated and submitted
|
||||
- User is redirected to test connection page after successful update
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- OCI provider row is visible in providers table
|
||||
@@ -760,7 +760,7 @@
|
||||
- Form submission succeeds (no silent failures due to missing provider UID)
|
||||
- Successful redirect to test connection page
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses same environment variables as PROVIDER-E2E-012 (add OCI provider)
|
||||
- Requires PROVIDER-E2E-012 to be run first to create the OCI provider
|
||||
@@ -788,7 +788,7 @@
|
||||
- Remove any existing provider with the same Account ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -802,14 +802,14 @@
|
||||
10. Verify redirect to Scans page
|
||||
11. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- AlibabaCloud provider successfully added with static credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays AlibabaCloud option
|
||||
@@ -822,7 +822,7 @@
|
||||
- Provider exists in Scans table (verified by account ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for AlibabaCloud credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -850,7 +850,7 @@
|
||||
- Remove any existing provider with the same Account ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Account ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -864,14 +864,14 @@
|
||||
10. Verify redirect to Scans page
|
||||
11. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- AlibabaCloud provider successfully added with RAM Role credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays AlibabaCloud option
|
||||
@@ -884,7 +884,7 @@
|
||||
- Provider exists in Scans table (verified by account ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for AlibabaCloud RAM Role credentials
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
@@ -914,7 +914,7 @@
|
||||
- StackSet must be deployed in AWS Organizations and expose a valid IAM Role ARN for Prowler
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Organization ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -927,14 +927,14 @@
|
||||
9. Verify organization launch step, choose single scan schedule, and launch
|
||||
10. Verify redirect to Scans page
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- AWS Organizations flow completes successfully
|
||||
- Accounts are connected and launch step is displayed
|
||||
- Scan scheduling selection is applied
|
||||
- User is redirected to Scans page after launch
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Connect account page displays AWS option
|
||||
- Organizations method selector is available
|
||||
@@ -943,7 +943,7 @@
|
||||
- Accounts connected launch step appears
|
||||
- Successful redirect to Scans page after launching
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Organization ID must follow AWS format (e.g., o-abc123def4)
|
||||
- Role ARN must belong to the StackSet deployment for Organizations flow
|
||||
@@ -970,7 +970,7 @@
|
||||
- Remove any existing provider with the same Customer ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Customer ID not to be already registered beforehand.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to providers page
|
||||
2. Click "Add Provider" button
|
||||
@@ -982,14 +982,14 @@
|
||||
8. Verify redirect to Scans page
|
||||
9. Verify scheduled scan status in Scans table (provider exists and scan name is "scheduled scan")
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Google Workspace provider successfully added with Service Account credentials
|
||||
- Initial scan launched successfully
|
||||
- User redirected to Scans page
|
||||
- Scheduled scan appears in Scans table with correct provider and scan name
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Provider page loads correctly
|
||||
- Connect account page displays Google Workspace option
|
||||
@@ -1003,7 +1003,7 @@
|
||||
- Provider exists in Scans table (verified by customer ID)
|
||||
- Scan name field contains "scheduled scan"
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test uses environment variables for Google Workspace credentials
|
||||
- Service Account JSON is provided as multi-line JSON string (not base64 encoded)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
- Remove any existing AWS provider with the same Account ID before starting the test
|
||||
- This test must be run serially and never in parallel with other tests, as it requires the Account ID Provider to be already registered.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to Scans page
|
||||
2. Open provider selector and choose the entry whose text contains E2E_AWS_PROVIDER_ACCOUNT_ID
|
||||
@@ -32,13 +32,13 @@
|
||||
5. Verify the success toast appears
|
||||
6. Verify a row in the Scans table contains the provided scan label (or shows the new scan entry)
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Scan is launched successfully
|
||||
- Success toast is displayed to the user
|
||||
- Scans table displays the new scan entry (including the alias when provided)
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- Scans page loads correctly
|
||||
- Provider select is available and lists the configured provider UID
|
||||
@@ -46,7 +46,7 @@
|
||||
- Success toast message: "The scan was launched successfully."
|
||||
- Table contains a row with the scan label or new scan state (queued/available/executing)
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- The table may take a short time to reflect the new scan; assertions look for a row containing the alias.
|
||||
- Provider cleanup performed before each test to ensure clean state
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Verify page is loaded.
|
||||
@@ -28,7 +28,7 @@
|
||||
4. Verify social buttons (Google, GitHub).
|
||||
5. Verify navigation links.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- All form elements are visible and properly labeled.
|
||||
|
||||
@@ -50,14 +50,14 @@
|
||||
- Application is running.
|
||||
- Valid test user credentials are configured via `ADMIN_USER` and `ADMIN_PASSWORD` environment variables.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Enter valid email and password.
|
||||
3. Click the login button.
|
||||
4. Verify successful redirect to home page.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- User is authenticated and redirected to the home page.
|
||||
|
||||
@@ -78,14 +78,14 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Enter invalid email and password.
|
||||
3. Click the login button.
|
||||
4. Verify error message is displayed.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Error message "Invalid email or password" is displayed.
|
||||
- User remains on the sign-in page.
|
||||
@@ -107,13 +107,13 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Click the login button without filling any fields.
|
||||
3. Verify validation errors are displayed.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Form validation errors are shown.
|
||||
- User remains on the sign-in page.
|
||||
@@ -135,14 +135,14 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Enter an invalid email format.
|
||||
3. Submit the form.
|
||||
4. Verify validation error is displayed.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Email format validation error is shown.
|
||||
|
||||
@@ -163,14 +163,14 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Fill only the email field.
|
||||
3. Submit the form.
|
||||
4. Verify password required error is displayed.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- "Password is required" error is shown.
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Click "Continue with SAML SSO" button.
|
||||
@@ -199,7 +199,7 @@
|
||||
4. Click back button.
|
||||
5. Verify normal mode is restored.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- SAML mode toggles correctly.
|
||||
- Password field visibility changes accordingly.
|
||||
@@ -221,14 +221,14 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Fill valid credentials.
|
||||
3. Submit the form.
|
||||
4. Verify loading state on button.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Login button shows loading state (disabled with aria-disabled).
|
||||
|
||||
@@ -249,14 +249,14 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Toggle SAML mode.
|
||||
3. Enter SAML email.
|
||||
4. Submit the form.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- SAML flow is initiated (would redirect to IdP in real scenario).
|
||||
|
||||
@@ -278,14 +278,14 @@
|
||||
- Application is running.
|
||||
- Valid test user credentials.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Verify successful login.
|
||||
3. Refresh the page.
|
||||
4. Verify user is still logged in.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Session persists after refresh.
|
||||
- User remains on the authenticated page.
|
||||
@@ -308,12 +308,12 @@
|
||||
- Application is running.
|
||||
- No active session.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate directly to a protected route (e.g., /providers).
|
||||
2. Verify redirect to sign-in page.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- User is redirected to /sign-in.
|
||||
|
||||
@@ -335,7 +335,7 @@
|
||||
- Application is running.
|
||||
- User is logged in.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Log in with valid credentials.
|
||||
2. Click logout/sign out.
|
||||
@@ -343,7 +343,7 @@
|
||||
4. Attempt to access protected route.
|
||||
5. Verify redirect to sign-in.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- User is logged out.
|
||||
- Session is invalidated.
|
||||
@@ -366,7 +366,7 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Create authenticated context and log in.
|
||||
2. Verify session exists.
|
||||
@@ -374,7 +374,7 @@
|
||||
4. Verify new context has no session.
|
||||
5. Verify new context is redirected to sign-in.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Sessions are isolated between contexts.
|
||||
- Unauthenticated context cannot access protected routes.
|
||||
@@ -396,13 +396,13 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Click the "Sign up" link.
|
||||
3. Verify redirect to sign-up page.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- User is navigated to /sign-up.
|
||||
|
||||
@@ -423,13 +423,13 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign up page.
|
||||
2. Click the login link.
|
||||
3. Verify redirect to sign-in page.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- User is navigated to /sign-in.
|
||||
|
||||
@@ -450,14 +450,14 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Navigate to the Sign up page.
|
||||
3. Click browser back button.
|
||||
4. Verify return to sign-in page.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Browser history navigation works correctly.
|
||||
|
||||
@@ -478,13 +478,13 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Use Tab key to navigate through form elements.
|
||||
3. Verify focus moves correctly through elements.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- All interactive elements are reachable via keyboard.
|
||||
- Focus order is logical.
|
||||
@@ -506,12 +506,12 @@
|
||||
|
||||
- Application is running.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign in page.
|
||||
2. Verify ARIA labels on form elements.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Email input has proper label.
|
||||
- Password input has proper label.
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- No existing data in Prowler is required; the test can run on a clean state.
|
||||
- `E2E_NEW_USER_PASSWORD` environment variable must be set with a valid password for the test.
|
||||
|
||||
### Flow Steps:
|
||||
### Flow Steps
|
||||
|
||||
1. Navigate to the Sign up page.
|
||||
2. Fill the form with valid data (unique email, valid password, terms accepted).
|
||||
@@ -30,18 +30,18 @@
|
||||
4. Verify redirect to the Login page.
|
||||
5. Log in with the newly created credentials.
|
||||
|
||||
### Expected Result:
|
||||
### Expected Result
|
||||
|
||||
- Sign-up succeeds and redirects to Login.
|
||||
- User can log in successfully using the created credentials and reach the home page.
|
||||
|
||||
### Key verification points:
|
||||
### Key verification points
|
||||
|
||||
- After submitting sign-up, the URL changes to `/sign-in`.
|
||||
- The newly created credentials can be used to sign in successfully.
|
||||
- After login, the user lands on the home (`/`) and main content is visible.
|
||||
|
||||
### Notes:
|
||||
### Notes
|
||||
|
||||
- Test data uses a random base36 suffix to avoid collisions with email.
|
||||
- The test requires the `E2E_NEW_USER_PASSWORD` environment variable to be set before running.
|
||||
|
||||
@@ -429,7 +429,7 @@ This is useful for:
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
```text
|
||||
[1] ✅ Created provider (id=db9a8985-f9ec-4dd8-b5a0-e05ab3880bed)
|
||||
[1] ✅ Created secret (id=466f76c6-5878-4602-a4bc-13f9522c1fd2)
|
||||
[1] ✅ Connection test: Connected
|
||||
@@ -454,25 +454,25 @@ python prowler_bulk_provisioning.py providers.yaml --dry-run
|
||||
### Common Issues
|
||||
|
||||
1. **Invalid API Key**
|
||||
```
|
||||
```text
|
||||
Error: 401 Unauthorized
|
||||
Solution: Check your PROWLER_API_KEY environment variable or --api-key parameter
|
||||
```
|
||||
|
||||
2. **Network Timeouts**
|
||||
```
|
||||
```text
|
||||
Error: Request timeout
|
||||
Solution: Increase --timeout value or check network connectivity
|
||||
```
|
||||
|
||||
3. **Invalid Provider Configuration**
|
||||
```
|
||||
```text
|
||||
Error: Each item must include 'provider' and 'uid'
|
||||
Solution: Verify all required fields are present in your config file
|
||||
```
|
||||
|
||||
4. **File Not Found Errors**
|
||||
```
|
||||
```text
|
||||
Error: No such file or directory
|
||||
Solution: Check file paths for credentials files (JSON keys, kubeconfig, etc.)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user