Compare commits

..

3 Commits

Author SHA1 Message Date
Adrián Jesús Peña Rodríguez
f5f4404ca9 chore: merge master 2026-02-26 19:13:58 +01:00
Adrián Jesús Peña Rodríguez
4dec30b4b6 fix(sdk): scope scan_id by provider and account
- Generate scan_id per provider account pair
- Adjust OCSF scan_id test to cover multiple accounts
2026-02-26 19:05:32 +01:00
Adrián Jesús Peña Rodríguez
c0e5a7ce97 feat(ingestions): allow multiple scan_ids and providers inside the ocsf 2026-02-26 17:16:51 +01:00
278 changed files with 1218 additions and 14728 deletions

View File

@@ -35,9 +35,7 @@ runs:
shell: bash
run: |
python -m pip install --upgrade pip
pipx install poetry==${INPUTS_POETRY_VERSION}
env:
INPUTS_POETRY_VERSION: ${{ inputs.poetry-version }}
pipx install poetry==${{ inputs.poetry-version }}
- name: Update poetry.lock with latest Prowler commit
if: github.repository_owner == 'prowler-cloud' && github.repository != 'prowler-cloud/prowler'

View File

@@ -26,18 +26,16 @@ runs:
id: status
shell: bash
run: |
if [[ "${INPUTS_STEP_OUTCOME}" == "success" ]]; then
if [[ "${{ inputs.step-outcome }}" == "success" ]]; then
echo "STATUS_TEXT=Completed" >> $GITHUB_ENV
echo "STATUS_COLOR=#6aa84f" >> $GITHUB_ENV
elif [[ "${INPUTS_STEP_OUTCOME}" == "failure" ]]; then
elif [[ "${{ inputs.step-outcome }}" == "failure" ]]; then
echo "STATUS_TEXT=Failed" >> $GITHUB_ENV
echo "STATUS_COLOR=#fc3434" >> $GITHUB_ENV
else
# No outcome provided - pending/in progress state
echo "STATUS_COLOR=#dbab09" >> $GITHUB_ENV
fi
env:
INPUTS_STEP_OUTCOME: ${{ inputs.step-outcome }}
- name: Send Slack notification (new message)
if: inputs.update-ts == ''
@@ -69,11 +67,8 @@ runs:
id: slack-notification
shell: bash
run: |
if [[ "${INPUTS_UPDATE_TS}" == "" ]]; then
echo "ts=${STEPS_SLACK_NOTIFICATION_POST_OUTPUTS_TS}" >> $GITHUB_OUTPUT
if [[ "${{ inputs.update-ts }}" == "" ]]; then
echo "ts=${{ steps.slack-notification-post.outputs.ts }}" >> $GITHUB_OUTPUT
else
echo "ts=${INPUTS_UPDATE_TS}" >> $GITHUB_OUTPUT
echo "ts=${{ inputs.update-ts }}" >> $GITHUB_OUTPUT
fi
env:
INPUTS_UPDATE_TS: ${{ inputs.update-ts }}
STEPS_SLACK_NOTIFICATION_POST_OUTPUTS_TS: ${{ steps.slack-notification-post.outputs.ts }}

View File

@@ -54,7 +54,7 @@ runs:
trivy-db-${{ runner.os }}-
- name: Run Trivy vulnerability scan (JSON)
uses: aquasecurity/trivy-action@e368e328979b113139d6f9068e03accaed98a518 # 0.34.1
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1
with:
image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }}
format: 'json'
@@ -63,11 +63,10 @@ runs:
exit-code: '0'
scanners: 'vuln'
timeout: '5m'
version: 'v0.69.2'
- name: Run Trivy vulnerability scan (SARIF)
if: inputs.upload-sarif == 'true' && github.event_name == 'push'
uses: aquasecurity/trivy-action@e368e328979b113139d6f9068e03accaed98a518 # 0.34.1
uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # v0.33.1
with:
image-ref: ${{ inputs.image-name }}:${{ inputs.image-tag }}
format: 'sarif'
@@ -76,7 +75,6 @@ runs:
exit-code: '0'
scanners: 'vuln'
timeout: '5m'
version: 'v0.69.2'
- name: Upload Trivy results to GitHub Security tab
if: inputs.upload-sarif == 'true' && github.event_name == 'push'
@@ -107,14 +105,11 @@ runs:
echo "### 🔒 Container Security Scan" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${INPUTS_IMAGE_NAME}:${INPUTS_IMAGE_TAG}\`" >> $GITHUB_STEP_SUMMARY
echo "**Image:** \`${{ inputs.image-name }}:${{ inputs.image-tag }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- 🔴 Critical: $CRITICAL" >> $GITHUB_STEP_SUMMARY
echo "- 🟠 High: $HIGH" >> $GITHUB_STEP_SUMMARY
echo "- **Total**: $TOTAL" >> $GITHUB_STEP_SUMMARY
env:
INPUTS_IMAGE_NAME: ${{ inputs.image-name }}
INPUTS_IMAGE_TAG: ${{ inputs.image-tag }}
- name: Comment scan results on PR
if: inputs.create-pr-comment == 'true' && github.event_name == 'pull_request'
@@ -128,7 +123,7 @@ runs:
const comment = require('./.github/scripts/trivy-pr-comment.js');
// Unique identifier to find our comment
const marker = `<!-- trivy-scan-comment:${process.env.IMAGE_NAME} -->`;
const marker = '<!-- trivy-scan-comment:${{ inputs.image-name }} -->';
const body = marker + '\n' + comment;
// Find existing comment
@@ -164,9 +159,6 @@ runs:
if: inputs.fail-on-critical == 'true' && steps.security-check.outputs.critical != '0'
shell: bash
run: |
echo "::error::Found ${STEPS_SECURITY_CHECK_OUTPUTS_CRITICAL} critical vulnerabilities"
echo "::error::Found ${{ steps.security-check.outputs.critical }} critical vulnerabilities"
echo "::warning::Please update packages or use a different base image"
exit 1
env:
STEPS_SECURITY_CHECK_OUTPUTS_CRITICAL: ${{ steps.security-check.outputs.critical }}

View File

@@ -15,8 +15,6 @@ updates:
labels:
- "dependencies"
- "pip"
cooldown:
default-days: 7
# Dependabot Updates are temporary disabled - 2025/03/19
# - package-ecosystem: "pip"
@@ -39,8 +37,6 @@ updates:
labels:
- "dependencies"
- "github_actions"
cooldown:
default-days: 7
# Dependabot Updates are temporary disabled - 2025/03/19
# - package-ecosystem: "npm"
@@ -63,8 +59,6 @@ updates:
labels:
- "dependencies"
- "docker"
cooldown:
default-days: 7
# Dependabot Updates are temporary disabled - 2025/04/15
# v4.6

View File

@@ -29,8 +29,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Get current API version
id: get_api_version
@@ -81,14 +79,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next API minor version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
CURRENT_API_VERSION="${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_API_VERSION}"
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
CURRENT_API_VERSION="${{ needs.detect-release-type.outputs.current_api_version }}"
# API version follows Prowler minor + 1
# For Prowler 5.17.0 -> API 1.18.0
@@ -101,10 +97,6 @@ jobs:
echo "Prowler release version: ${MAJOR_VERSION}.${MINOR_VERSION}.0"
echo "Current API version: $CURRENT_API_VERSION"
echo "Next API minor version (for master): $NEXT_API_VERSION"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_API_VERSION: ${{ needs.detect-release-type.outputs.current_api_version }}
- name: Bump API versions in files for master
run: |
@@ -140,13 +132,12 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: v${{ needs.detect-release-type.outputs.major_version }}.${{ needs.detect-release-type.outputs.minor_version }}
persist-credentials: false
- name: Calculate first API patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
CURRENT_API_VERSION="${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_API_VERSION}"
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
CURRENT_API_VERSION="${{ needs.detect-release-type.outputs.current_api_version }}"
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
# API version follows Prowler minor + 1
@@ -160,10 +151,6 @@ jobs:
echo "Prowler release version: ${MAJOR_VERSION}.${MINOR_VERSION}.0"
echo "First API patch version (for ${VERSION_BRANCH}): $FIRST_API_PATCH_VERSION"
echo "Version branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_API_VERSION: ${{ needs.detect-release-type.outputs.current_api_version }}
- name: Bump API versions in files for version branch
run: |
@@ -206,15 +193,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next API patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
PATCH_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION}
CURRENT_API_VERSION="${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_API_VERSION}"
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
PATCH_VERSION=${{ needs.detect-release-type.outputs.patch_version }}
CURRENT_API_VERSION="${{ needs.detect-release-type.outputs.current_api_version }}"
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
# Extract current API patch to increment it
@@ -237,11 +222,6 @@ jobs:
echo "::error::Invalid API version format: $CURRENT_API_VERSION"
exit 1
fi
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION: ${{ needs.detect-release-type.outputs.patch_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_API_VERSION: ${{ needs.detect-release-type.outputs.current_api_version }}
- name: Bump API versions in files for version branch
run: |

View File

@@ -34,9 +34,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for API changes
id: check-changes

View File

@@ -43,8 +43,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9

View File

@@ -58,8 +58,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Notify container push started
id: slack-notification
@@ -96,8 +94,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Login to DockerHub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@@ -142,22 +138,18 @@ jobs:
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.LATEST_TAG }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64
- name: Create and push manifests for release event
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${RELEASE_TAG} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.RELEASE_TAG }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.STABLE_TAG }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64
- name: Install regctl
if: always()
@@ -167,11 +159,9 @@ jobs:
if: always()
run: |
echo "Cleaning up intermediate tags..."
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64" || true
echo "Cleanup completed"
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
notify-release-completed:
if: always() && needs.notify-release-started.result == 'success' && (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
@@ -181,20 +171,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Determine overall outcome
id: outcome
run: |
if [[ "${NEEDS_CONTAINER_BUILD_PUSH_RESULT}" == "success" && "${NEEDS_CREATE_MANIFEST_RESULT}" == "success" ]]; then
if [[ "${{ needs.container-build-push.result }}" == "success" && "${{ needs.create-manifest.result }}" == "success" ]]; then
echo "outcome=success" >> $GITHUB_OUTPUT
else
echo "outcome=failure" >> $GITHUB_OUTPUT
fi
env:
NEEDS_CONTAINER_BUILD_PUSH_RESULT: ${{ needs.container-build-push.result }}
NEEDS_CREATE_MANIFEST_RESULT: ${{ needs.create-manifest.result }}
- name: Notify container push completed
uses: ./.github/actions/slack-notification

View File

@@ -29,9 +29,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check if Dockerfile changed
id: dockerfile-changed
@@ -67,9 +64,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for API changes
id: check-changes

View File

@@ -34,9 +34,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for API changes
id: check-changes

View File

@@ -43,7 +43,7 @@ jobs:
services:
postgres:
image: postgres:17@sha256:2cd82735a36356842d5eb1ef80db3ae8f1154172f0f653db48fde079b2a0b7f7
image: postgres
env:
POSTGRES_HOST: ${{ env.POSTGRES_HOST }}
POSTGRES_PORT: ${{ env.POSTGRES_PORT }}
@@ -74,9 +74,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for API changes
id: check-changes

View File

@@ -1,7 +1,6 @@
name: 'Tools: Backport'
on:
# zizmor: ignore[dangerous-triggers] - intentional: needs write access for backport PRs, no PR code checkout
pull_request_target:
branches:
- 'master'

View File

@@ -1,44 +0,0 @@
name: 'CI: Zizmor'
on:
push:
branches:
- 'master'
- 'v5.*'
paths:
- '.github/**'
pull_request:
branches:
- 'master'
- 'v5.*'
paths:
- '.github/**'
schedule:
- cron: '30 06 * * *'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
zizmor:
if: github.repository == 'prowler-cloud/prowler'
name: GitHub Actions Security Audit
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
security-events: write
contents: read
actions: read
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Run zizmor
uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0
with:
token: ${{ github.token }}

View File

@@ -25,9 +25,8 @@ jobs:
- name: Create backport label for minor releases
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT_RELEASE_TAG_NAME: ${{ github.event.release.tag_name }}
run: |
RELEASE_TAG="${GITHUB_EVENT_RELEASE_TAG_NAME}"
RELEASE_TAG="${{ github.event.release.tag_name }}"
if [ -z "$RELEASE_TAG" ]; then
echo "Error: No release tag provided"

View File

@@ -29,8 +29,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Get current documentation version
id: get_docs_version
@@ -81,14 +79,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next minor version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
CURRENT_DOCS_VERSION="${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_DOCS_VERSION}"
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
CURRENT_DOCS_VERSION="${{ needs.detect-release-type.outputs.current_docs_version }}"
NEXT_MINOR_VERSION=${MAJOR_VERSION}.$((MINOR_VERSION + 1)).0
echo "CURRENT_DOCS_VERSION=${CURRENT_DOCS_VERSION}" >> "${GITHUB_ENV}"
@@ -97,10 +93,6 @@ jobs:
echo "Current documentation version: $CURRENT_DOCS_VERSION"
echo "Current release version: $PROWLER_VERSION"
echo "Next minor version: $NEXT_MINOR_VERSION"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_DOCS_VERSION: ${{ needs.detect-release-type.outputs.current_docs_version }}
- name: Bump versions in documentation for master
run: |
@@ -140,13 +132,12 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: v${{ needs.detect-release-type.outputs.major_version }}.${{ needs.detect-release-type.outputs.minor_version }}
persist-credentials: false
- name: Calculate first patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
CURRENT_DOCS_VERSION="${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_DOCS_VERSION}"
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
CURRENT_DOCS_VERSION="${{ needs.detect-release-type.outputs.current_docs_version }}"
FIRST_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.1
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
@@ -157,10 +148,6 @@ jobs:
echo "First patch version: $FIRST_PATCH_VERSION"
echo "Version branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_DOCS_VERSION: ${{ needs.detect-release-type.outputs.current_docs_version }}
- name: Bump versions in documentation for version branch
run: |
@@ -206,15 +193,13 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
PATCH_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION}
CURRENT_DOCS_VERSION="${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_DOCS_VERSION}"
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
PATCH_VERSION=${{ needs.detect-release-type.outputs.patch_version }}
CURRENT_DOCS_VERSION="${{ needs.detect-release-type.outputs.current_docs_version }}"
NEXT_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.$((PATCH_VERSION + 1))
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
@@ -227,11 +212,6 @@ jobs:
echo "Current release version: $PROWLER_VERSION"
echo "Next patch version: $NEXT_PATCH_VERSION"
echo "Target branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION: ${{ needs.detect-release-type.outputs.patch_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_CURRENT_DOCS_VERSION: ${{ needs.detect-release-type.outputs.current_docs_version }}
- name: Bump versions in documentation for patch version
run: |

View File

@@ -26,7 +26,6 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Scan for secrets with TruffleHog
uses: trufflesecurity/trufflehog@ef6e76c3c4023279497fab4721ffa071a722fd05 # v3.92.4

View File

@@ -1,7 +1,6 @@
name: 'Tools: PR Labeler'
on:
# zizmor: ignore[dangerous-triggers] - intentional: needs write access to apply labels, no PR code checkout
pull_request_target:
branches:
- 'master'

View File

@@ -57,8 +57,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Notify container push started
id: slack-notification
@@ -94,8 +92,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Login to DockerHub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@@ -148,36 +144,30 @@ jobs:
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.LATEST_TAG }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64
- name: Create and push manifests for release event
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${RELEASE_TAG} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.RELEASE_TAG }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.STABLE_TAG }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64
- name: Install regctl
if: always()
uses: regclient/actions/regctl-installer@da9319db8e44e8b062b3a147e1dfb2f574d41a03 # main
uses: regclient/actions/regctl-installer@main
- name: Cleanup intermediate architecture tags
if: always()
run: |
echo "Cleaning up intermediate tags..."
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64" || true
echo "Cleanup completed"
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
notify-release-completed:
if: always() && needs.notify-release-started.result == 'success' && (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
@@ -187,20 +177,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Determine overall outcome
id: outcome
run: |
if [[ "${NEEDS_CONTAINER_BUILD_PUSH_RESULT}" == "success" && "${NEEDS_CREATE_MANIFEST_RESULT}" == "success" ]]; then
if [[ "${{ needs.container-build-push.result }}" == "success" && "${{ needs.create-manifest.result }}" == "success" ]]; then
echo "outcome=success" >> $GITHUB_OUTPUT
else
echo "outcome=failure" >> $GITHUB_OUTPUT
fi
env:
NEEDS_CONTAINER_BUILD_PUSH_RESULT: ${{ needs.container-build-push.result }}
NEEDS_CREATE_MANIFEST_RESULT: ${{ needs.create-manifest.result }}
- name: Notify container push completed
uses: ./.github/actions/slack-notification

View File

@@ -29,9 +29,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check if Dockerfile changed
id: dockerfile-changed
@@ -66,9 +63,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for MCP changes
id: check-changes

View File

@@ -29,7 +29,7 @@ jobs:
- name: Parse and validate version
id: parse-version
run: |
PROWLER_VERSION="${RELEASE_TAG}"
PROWLER_VERSION="${{ env.RELEASE_TAG }}"
echo "version=${PROWLER_VERSION}" >> "${GITHUB_OUTPUT}"
# Extract major version
@@ -61,13 +61,9 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install uv
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v7
with:
enable-cache: false
uses: astral-sh/setup-uv@v7
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0

View File

@@ -32,8 +32,6 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
fetch-depth: 0
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Get changed files
id: changed-files
@@ -52,11 +50,11 @@ jobs:
run: |
missing_changelogs=""
if [[ "${STEPS_CHANGED_FILES_OUTPUTS_ANY_CHANGED}" == "true" ]]; then
if [[ "${{ steps.changed-files.outputs.any_changed }}" == "true" ]]; then
# Check monitored folders
for folder in $MONITORED_FOLDERS; do
# Get files changed in this folder
changed_in_folder=$(echo "${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}" | tr ' ' '\n' | grep "^${folder}/" || true)
changed_in_folder=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' | grep "^${folder}/" || true)
if [ -n "$changed_in_folder" ]; then
echo "Detected changes in ${folder}/"
@@ -71,11 +69,11 @@ jobs:
# Check root-level dependency files (poetry.lock, pyproject.toml)
# These are associated with the prowler folder changelog
root_deps_changed=$(echo "${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}" | tr ' ' '\n' | grep -E "^(poetry\.lock|pyproject\.toml)$" || true)
root_deps_changed=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' | grep -E "^(poetry\.lock|pyproject\.toml)$" || true)
if [ -n "$root_deps_changed" ]; then
echo "Detected changes in root dependency files: $root_deps_changed"
# Check if prowler/CHANGELOG.md was already updated (might have been caught above)
prowler_changelog_updated=$(echo "${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}" | tr ' ' '\n' | grep "^prowler/CHANGELOG.md$" || true)
prowler_changelog_updated=$(echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n' | grep "^prowler/CHANGELOG.md$" || true)
if [ -z "$prowler_changelog_updated" ]; then
# Only add if prowler wasn't already flagged
if ! echo "$missing_changelogs" | grep -q "prowler"; then
@@ -91,9 +89,6 @@ jobs:
echo -e "${missing_changelogs}"
echo "EOF"
} >> $GITHUB_OUTPUT
env:
STEPS_CHANGED_FILES_OUTPUTS_ANY_CHANGED: ${{ steps.changed-files.outputs.any_changed }}
STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
- name: Find existing changelog comment
if: github.event.pull_request.head.repo.full_name == github.repository

View File

@@ -1,7 +1,6 @@
name: 'Tools: PR Conflict Checker'
on:
# zizmor: ignore[dangerous-triggers] - intentional: needs write access for conflict labels/comments, checkout uses PR head SHA for read-only grep
pull_request_target:
types:
- 'opened'
@@ -30,7 +29,6 @@ jobs:
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
- name: Get changed files
id: changed-files
@@ -47,7 +45,7 @@ jobs:
HAS_CONFLICTS=false
# Check each changed file for conflict markers
for file in ${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}; do
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
if [ -f "$file" ]; then
echo "Checking file: $file"
@@ -72,8 +70,6 @@ jobs:
echo "has_conflicts=false" >> $GITHUB_OUTPUT
echo "No conflict markers found in changed files"
fi
env:
STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
- name: Manage conflict label
env:

View File

@@ -1,7 +1,6 @@
name: 'Tools: PR Merged'
on:
# zizmor: ignore[dangerous-triggers] - intentional: needs read access to merged PR metadata, no PR code checkout
pull_request_target:
branches:
- 'master'
@@ -26,10 +25,8 @@ jobs:
- name: Calculate short commit SHA
id: vars
run: |
SHORT_SHA="${GITHUB_EVENT_PULL_REQUEST_MERGE_COMMIT_SHA}"
echo "short_sha=${SHORT_SHA::7}" >> $GITHUB_OUTPUT
env:
GITHUB_EVENT_PULL_REQUEST_MERGE_COMMIT_SHA: ${{ github.event.pull_request.merge_commit_sha }}
SHORT_SHA="${{ github.event.pull_request.merge_commit_sha }}"
echo "SHORT_SHA=${SHORT_SHA::7}" >> $GITHUB_ENV
- name: Trigger Cloud repository pull request
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1
@@ -40,7 +37,7 @@ jobs:
client-payload: |
{
"PROWLER_COMMIT_SHA": "${{ github.event.pull_request.merge_commit_sha }}",
"PROWLER_COMMIT_SHORT_SHA": "${{ steps.vars.outputs.short_sha }}",
"PROWLER_COMMIT_SHORT_SHA": "${{ env.SHORT_SHA }}",
"PROWLER_PR_NUMBER": "${{ github.event.pull_request.number }}",
"PROWLER_PR_TITLE": ${{ toJson(github.event.pull_request.title) }},
"PROWLER_PR_LABELS": ${{ toJson(github.event.pull_request.labels.*.name) }},

View File

@@ -31,7 +31,6 @@ jobs:
with:
fetch-depth: 0
token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }}
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0

View File

@@ -68,22 +68,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next minor version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
NEXT_MINOR_VERSION=${MAJOR_VERSION}.$((MINOR_VERSION + 1)).0
echo "NEXT_MINOR_VERSION=${NEXT_MINOR_VERSION}" >> "${GITHUB_ENV}"
echo "Current version: $PROWLER_VERSION"
echo "Next minor version: $NEXT_MINOR_VERSION"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
- name: Bump versions in files for master
run: |
@@ -118,12 +113,11 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: v${{ needs.detect-release-type.outputs.major_version }}.${{ needs.detect-release-type.outputs.minor_version }}
persist-credentials: false
- name: Calculate first patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
FIRST_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.1
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
@@ -133,9 +127,6 @@ jobs:
echo "First patch version: $FIRST_PATCH_VERSION"
echo "Version branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
- name: Bump versions in files for version branch
run: |
@@ -177,14 +168,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
PATCH_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION}
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
PATCH_VERSION=${{ needs.detect-release-type.outputs.patch_version }}
NEXT_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.$((PATCH_VERSION + 1))
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
@@ -195,10 +184,6 @@ jobs:
echo "Current version: $PROWLER_VERSION"
echo "Next patch version: $NEXT_PATCH_VERSION"
echo "Target branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION: ${{ needs.detect-release-type.outputs.patch_version }}
- name: Bump versions in files for version branch
run: |

View File

@@ -21,8 +21,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Check for duplicate test names across providers
run: |

View File

@@ -32,9 +32,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for SDK changes
id: check-changes

View File

@@ -50,8 +50,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9

View File

@@ -62,8 +62,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
@@ -118,8 +116,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Notify container push started
id: slack-notification
@@ -156,8 +152,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Login to DockerHub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@@ -220,44 +214,36 @@ jobs:
if: github.event_name == 'push'
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG} \
-t ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG} \
-t ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG}-arm64
env:
NEEDS_SETUP_OUTPUTS_LATEST_TAG: ${{ needs.setup.outputs.latest_tag }}
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }} \
-t ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }} \
-t ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }}-arm64
- name: Create and push manifests for release event
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
run: |
docker buildx imagetools create \
-t ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${NEEDS_SETUP_OUTPUTS_PROWLER_VERSION} \
-t ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${NEEDS_SETUP_OUTPUTS_STABLE_TAG} \
-t ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${NEEDS_SETUP_OUTPUTS_PROWLER_VERSION} \
-t ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${NEEDS_SETUP_OUTPUTS_STABLE_TAG} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_PROWLER_VERSION} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_STABLE_TAG} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG}-arm64
env:
NEEDS_SETUP_OUTPUTS_PROWLER_VERSION: ${{ needs.setup.outputs.prowler_version }}
NEEDS_SETUP_OUTPUTS_STABLE_TAG: ${{ needs.setup.outputs.stable_tag }}
NEEDS_SETUP_OUTPUTS_LATEST_TAG: ${{ needs.setup.outputs.latest_tag }}
-t ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ needs.setup.outputs.prowler_version }} \
-t ${{ secrets.DOCKER_HUB_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ needs.setup.outputs.stable_tag }} \
-t ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ needs.setup.outputs.prowler_version }} \
-t ${{ secrets.PUBLIC_ECR_REPOSITORY }}/${{ env.IMAGE_NAME }}:${{ needs.setup.outputs.stable_tag }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.prowler_version }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.stable_tag }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }}-arm64
- name: Install regctl
if: always()
uses: regclient/actions/regctl-installer@da9319db8e44e8b062b3a147e1dfb2f574d41a03 # main
uses: regclient/actions/regctl-installer@main
- name: Cleanup intermediate architecture tags
if: always()
run: |
echo "Cleaning up intermediate tags..."
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_LATEST_TAG}-arm64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.latest_tag }}-arm64" || true
echo "Cleanup completed"
env:
NEEDS_SETUP_OUTPUTS_LATEST_TAG: ${{ needs.setup.outputs.latest_tag }}
notify-release-completed:
if: always() && needs.notify-release-started.result == 'success' && (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
@@ -267,20 +253,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Determine overall outcome
id: outcome
run: |
if [[ "${NEEDS_CONTAINER_BUILD_PUSH_RESULT}" == "success" && "${NEEDS_CREATE_MANIFEST_RESULT}" == "success" ]]; then
if [[ "${{ needs.container-build-push.result }}" == "success" && "${{ needs.create-manifest.result }}" == "success" ]]; then
echo "outcome=success" >> $GITHUB_OUTPUT
else
echo "outcome=failure" >> $GITHUB_OUTPUT
fi
env:
NEEDS_CONTAINER_BUILD_PUSH_RESULT: ${{ needs.container-build-push.result }}
NEEDS_CREATE_MANIFEST_RESULT: ${{ needs.create-manifest.result }}
- name: Notify container push completed
uses: ./.github/actions/slack-notification

View File

@@ -28,9 +28,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check if Dockerfile changed
id: dockerfile-changed
@@ -66,9 +63,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for SDK changes
id: check-changes

View File

@@ -28,7 +28,7 @@ jobs:
- name: Parse and validate version
id: parse-version
run: |
PROWLER_VERSION="${RELEASE_TAG}"
PROWLER_VERSION="${{ env.RELEASE_TAG }}"
echo "version=${PROWLER_VERSION}" >> "${GITHUB_OUTPUT}"
# Extract major version
@@ -60,8 +60,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install Poetry
run: pipx install poetry==2.1.1
@@ -70,6 +68,7 @@ jobs:
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'poetry'
- name: Build Prowler package
run: poetry build
@@ -93,8 +92,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Install Poetry
run: pipx install poetry==2.1.1
@@ -103,6 +100,7 @@ jobs:
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
with:
python-version: ${{ env.PYTHON_VERSION }}
cache: 'poetry'
- name: Install toml package
run: pip install toml

View File

@@ -28,7 +28,6 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: 'master'
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
@@ -83,14 +82,9 @@ jobs:
- name: PR creation result
run: |
if [[ "${STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_NUMBER}" ]]; then
echo "✓ Pull request #${STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_NUMBER} created successfully"
echo "URL: ${STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_URL}"
if [[ "${{ steps.create-pr.outputs.pull-request-number }}" ]]; then
echo "✓ Pull request #${{ steps.create-pr.outputs.pull-request-number }} created successfully"
echo "URL: ${{ steps.create-pr.outputs.pull-request-url }}"
else
echo "✓ No changes detected - AWS regions are up to date"
fi
env:
STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }}
STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_URL: ${{ steps.create-pr.outputs.pull-request-url }}

View File

@@ -26,7 +26,6 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: 'master'
persist-credentials: false
- name: Set up Python ${{ env.PYTHON_VERSION }}
uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
@@ -86,14 +85,9 @@ jobs:
- name: PR creation result
run: |
if [[ "${STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_NUMBER}" ]]; then
echo "✓ Pull request #${STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_NUMBER} created successfully"
echo "URL: ${STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_URL}"
if [[ "${{ steps.create-pr.outputs.pull-request-number }}" ]]; then
echo "✓ Pull request #${{ steps.create-pr.outputs.pull-request-number }} created successfully"
echo "URL: ${{ steps.create-pr.outputs.pull-request-url }}"
else
echo "✓ No changes detected - OCI regions are up to date"
fi
env:
STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_NUMBER: ${{ steps.create-pr.outputs.pull-request-number }}
STEPS_CREATE_PR_OUTPUTS_PULL_REQUEST_URL: ${{ steps.create-pr.outputs.pull-request-url }}

View File

@@ -25,15 +25,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for SDK changes
id: check-changes
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891 # v47.0.1
with:
files:
files:
./**
.github/workflows/sdk-security.yml
files_ignore: |

View File

@@ -32,9 +32,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for SDK changes
id: check-changes
@@ -122,7 +119,7 @@ jobs:
"wafv2": ["cognito", "elbv2"],
}
changed_raw = os.environ.get("STEPS_CHANGED_AWS_OUTPUTS_ALL_CHANGED_FILES", "")
changed_raw = """${{ steps.changed-aws.outputs.all_changed_files }}"""
# all_changed_files is space-separated, not newline-separated
# Strip leading "./" if present for consistent path handling
changed_files = [Path(f.lstrip("./")) for f in changed_raw.split() if f]
@@ -177,25 +174,20 @@ jobs:
else:
print("AWS service test paths: none detected")
PY
env:
STEPS_CHANGED_AWS_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-aws.outputs.all_changed_files }}
- name: Run AWS tests
if: steps.changed-aws.outputs.any_changed == 'true'
run: |
echo "AWS run_all=${STEPS_AWS_SERVICES_OUTPUTS_RUN_ALL}"
echo "AWS service_paths='${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}'"
echo "AWS run_all=${{ steps.aws-services.outputs.run_all }}"
echo "AWS service_paths='${{ steps.aws-services.outputs.service_paths }}'"
if [ "${STEPS_AWS_SERVICES_OUTPUTS_RUN_ALL}" = "true" ]; then
if [ "${{ steps.aws-services.outputs.run_all }}" = "true" ]; then
poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml tests/providers/aws
elif [ -z "${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}" ]; then
elif [ -z "${{ steps.aws-services.outputs.service_paths }}" ]; then
echo "No AWS service paths detected; skipping AWS tests."
else
poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml ${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}
poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml ${{ steps.aws-services.outputs.service_paths }}
fi
env:
STEPS_AWS_SERVICES_OUTPUTS_RUN_ALL: ${{ steps.aws-services.outputs.run_all }}
STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS: ${{ steps.aws-services.outputs.service_paths }}
- name: Upload AWS coverage to Codecov
if: steps.changed-aws.outputs.any_changed == 'true'

View File

@@ -49,9 +49,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Get changed files
id: changed-files
@@ -69,60 +66,47 @@ jobs:
id: impact
run: |
echo "Changed files:"
echo "${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}" | tr ' ' '\n'
echo "${{ steps.changed-files.outputs.all_changed_files }}" | tr ' ' '\n'
echo ""
python .github/scripts/test-impact.py ${STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES}
env:
STEPS_CHANGED_FILES_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
python .github/scripts/test-impact.py ${{ steps.changed-files.outputs.all_changed_files }}
- name: Set convenience flags
id: set-flags
run: |
if [[ -n "${STEPS_IMPACT_OUTPUTS_SDK_TESTS}" ]]; then
if [[ -n "${{ steps.impact.outputs.sdk-tests }}" ]]; then
echo "has-sdk-tests=true" >> $GITHUB_OUTPUT
else
echo "has-sdk-tests=false" >> $GITHUB_OUTPUT
fi
if [[ -n "${STEPS_IMPACT_OUTPUTS_API_TESTS}" ]]; then
if [[ -n "${{ steps.impact.outputs.api-tests }}" ]]; then
echo "has-api-tests=true" >> $GITHUB_OUTPUT
else
echo "has-api-tests=false" >> $GITHUB_OUTPUT
fi
if [[ -n "${STEPS_IMPACT_OUTPUTS_UI_E2E}" ]]; then
if [[ -n "${{ steps.impact.outputs.ui-e2e }}" ]]; then
echo "has-ui-e2e=true" >> $GITHUB_OUTPUT
else
echo "has-ui-e2e=false" >> $GITHUB_OUTPUT
fi
env:
STEPS_IMPACT_OUTPUTS_SDK_TESTS: ${{ steps.impact.outputs.sdk-tests }}
STEPS_IMPACT_OUTPUTS_API_TESTS: ${{ steps.impact.outputs.api-tests }}
STEPS_IMPACT_OUTPUTS_UI_E2E: ${{ steps.impact.outputs.ui-e2e }}
- name: Summary
run: |
echo "## Test Impact Analysis" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [[ "${STEPS_IMPACT_OUTPUTS_RUN_ALL}" == "true" ]]; then
if [[ "${{ steps.impact.outputs.run-all }}" == "true" ]]; then
echo "🚨 **Critical path changed - running ALL tests**" >> $GITHUB_STEP_SUMMARY
else
echo "### Affected Modules" >> $GITHUB_STEP_SUMMARY
echo "\`${STEPS_IMPACT_OUTPUTS_MODULES}\`" >> $GITHUB_STEP_SUMMARY
echo "\`${{ steps.impact.outputs.modules }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Tests to Run" >> $GITHUB_STEP_SUMMARY
echo "| Category | Paths |" >> $GITHUB_STEP_SUMMARY
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
echo "| SDK Tests | \`${STEPS_IMPACT_OUTPUTS_SDK_TESTS:-none}\` |" >> $GITHUB_STEP_SUMMARY
echo "| API Tests | \`${STEPS_IMPACT_OUTPUTS_API_TESTS:-none}\` |" >> $GITHUB_STEP_SUMMARY
echo "| UI E2E | \`${STEPS_IMPACT_OUTPUTS_UI_E2E:-none}\` |" >> $GITHUB_STEP_SUMMARY
echo "| SDK Tests | \`${{ steps.impact.outputs.sdk-tests || 'none' }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| API Tests | \`${{ steps.impact.outputs.api-tests || 'none' }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| UI E2E | \`${{ steps.impact.outputs.ui-e2e || 'none' }}\` |" >> $GITHUB_STEP_SUMMARY
fi
env:
STEPS_IMPACT_OUTPUTS_RUN_ALL: ${{ steps.impact.outputs.run-all }}
STEPS_IMPACT_OUTPUTS_SDK_TESTS: ${{ steps.impact.outputs.sdk-tests }}
STEPS_IMPACT_OUTPUTS_API_TESTS: ${{ steps.impact.outputs.api-tests }}
STEPS_IMPACT_OUTPUTS_UI_E2E: ${{ steps.impact.outputs.ui-e2e }}
STEPS_IMPACT_OUTPUTS_MODULES: ${{ steps.impact.outputs.modules }}

View File

@@ -68,22 +68,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next minor version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
NEXT_MINOR_VERSION=${MAJOR_VERSION}.$((MINOR_VERSION + 1)).0
echo "NEXT_MINOR_VERSION=${NEXT_MINOR_VERSION}" >> "${GITHUB_ENV}"
echo "Current version: $PROWLER_VERSION"
echo "Next minor version: $NEXT_MINOR_VERSION"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
- name: Bump UI version in .env for master
run: |
@@ -120,12 +115,11 @@ jobs:
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
ref: v${{ needs.detect-release-type.outputs.major_version }}.${{ needs.detect-release-type.outputs.minor_version }}
persist-credentials: false
- name: Calculate first patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
FIRST_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.1
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
@@ -135,9 +129,6 @@ jobs:
echo "First patch version: $FIRST_PATCH_VERSION"
echo "Version branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
- name: Bump UI version in .env for version branch
run: |
@@ -181,14 +172,12 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Calculate next patch version
run: |
MAJOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION}
MINOR_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION}
PATCH_VERSION=${NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION}
MAJOR_VERSION=${{ needs.detect-release-type.outputs.major_version }}
MINOR_VERSION=${{ needs.detect-release-type.outputs.minor_version }}
PATCH_VERSION=${{ needs.detect-release-type.outputs.patch_version }}
NEXT_PATCH_VERSION=${MAJOR_VERSION}.${MINOR_VERSION}.$((PATCH_VERSION + 1))
VERSION_BRANCH=v${MAJOR_VERSION}.${MINOR_VERSION}
@@ -199,10 +188,6 @@ jobs:
echo "Current version: $PROWLER_VERSION"
echo "Next patch version: $NEXT_PATCH_VERSION"
echo "Target branch: $VERSION_BRANCH"
env:
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MAJOR_VERSION: ${{ needs.detect-release-type.outputs.major_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_MINOR_VERSION: ${{ needs.detect-release-type.outputs.minor_version }}
NEEDS_DETECT_RELEASE_TYPE_OUTPUTS_PATCH_VERSION: ${{ needs.detect-release-type.outputs.patch_version }}
- name: Bump UI version in .env for version branch
run: |

View File

@@ -46,8 +46,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9

View File

@@ -60,8 +60,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Notify container push started
id: slack-notification
@@ -98,8 +96,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Login to DockerHub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
@@ -147,36 +143,30 @@ jobs:
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.LATEST_TAG }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64
- name: Create and push manifests for release event
if: github.event_name == 'release' || github.event_name == 'workflow_dispatch'
run: |
docker buildx imagetools create \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${RELEASE_TAG} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.RELEASE_TAG }} \
-t ${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ env.STABLE_TAG }} \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64 \
${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64
- name: Install regctl
if: always()
uses: regclient/actions/regctl-installer@da9319db8e44e8b062b3a147e1dfb2f574d41a03 # main
uses: regclient/actions/regctl-installer@main
- name: Cleanup intermediate architecture tags
if: always()
run: |
echo "Cleaning up intermediate tags..."
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${NEEDS_SETUP_OUTPUTS_SHORT_SHA}-arm64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-amd64" || true
regctl tag delete "${{ env.PROWLERCLOUD_DOCKERHUB_REPOSITORY }}/${{ env.PROWLERCLOUD_DOCKERHUB_IMAGE }}:${{ needs.setup.outputs.short-sha }}-arm64" || true
echo "Cleanup completed"
env:
NEEDS_SETUP_OUTPUTS_SHORT_SHA: ${{ needs.setup.outputs.short-sha }}
notify-release-completed:
if: always() && needs.notify-release-started.result == 'success' && (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
@@ -186,20 +176,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Determine overall outcome
id: outcome
run: |
if [[ "${NEEDS_CONTAINER_BUILD_PUSH_RESULT}" == "success" && "${NEEDS_CREATE_MANIFEST_RESULT}" == "success" ]]; then
if [[ "${{ needs.container-build-push.result }}" == "success" && "${{ needs.create-manifest.result }}" == "success" ]]; then
echo "outcome=success" >> $GITHUB_OUTPUT
else
echo "outcome=failure" >> $GITHUB_OUTPUT
fi
env:
NEEDS_CONTAINER_BUILD_PUSH_RESULT: ${{ needs.container-build-push.result }}
NEEDS_CREATE_MANIFEST_RESULT: ${{ needs.create-manifest.result }}
- name: Notify container push completed
uses: ./.github/actions/slack-notification

View File

@@ -29,9 +29,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check if Dockerfile changed
id: dockerfile-changed
@@ -67,9 +64,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for UI changes
id: check-changes

View File

@@ -15,9 +15,6 @@ on:
- 'ui/**'
- 'api/**' # API changes can affect UI E2E
permissions:
contents: read
jobs:
# First, analyze which tests need to run
impact-analysis:
@@ -79,24 +76,20 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- name: Show test scope
run: |
echo "## E2E Test Scope" >> $GITHUB_STEP_SUMMARY
if [[ "${RUN_ALL_TESTS}" == "true" ]]; then
if [[ "${{ env.RUN_ALL_TESTS }}" == "true" ]]; then
echo "Running **ALL** E2E tests (critical path changed)" >> $GITHUB_STEP_SUMMARY
else
echo "Running tests matching: \`${E2E_TEST_PATHS}\`" >> $GITHUB_STEP_SUMMARY
echo "Running tests matching: \`${{ env.E2E_TEST_PATHS }}\`" >> $GITHUB_STEP_SUMMARY
fi
echo ""
echo "Affected modules: \`${NEEDS_IMPACT_ANALYSIS_OUTPUTS_MODULES}\`" >> $GITHUB_STEP_SUMMARY
env:
NEEDS_IMPACT_ANALYSIS_OUTPUTS_MODULES: ${{ needs.impact-analysis.outputs.modules }}
echo "Affected modules: \`${{ needs.impact-analysis.outputs.modules }}\`" >> $GITHUB_STEP_SUMMARY
- name: Create k8s Kind Cluster
uses: helm/kind-action@ef37e7f390d99f746eb8b610417061a60e82a6cc # v1
uses: helm/kind-action@v1
with:
cluster_name: kind
@@ -157,7 +150,7 @@ jobs:
node-version: '24.13.0'
- name: Setup pnpm
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4
uses: pnpm/action-setup@v4
with:
version: 10
run_install: false
@@ -202,14 +195,14 @@ jobs:
- name: Run E2E tests
working-directory: ./ui
run: |
if [[ "${RUN_ALL_TESTS}" == "true" ]]; then
if [[ "${{ env.RUN_ALL_TESTS }}" == "true" ]]; then
echo "Running ALL E2E tests..."
pnpm run test:e2e
else
echo "Running targeted E2E tests: ${E2E_TEST_PATHS}"
echo "Running targeted E2E tests: ${{ env.E2E_TEST_PATHS }}"
# Convert glob patterns to playwright test paths
# e.g., "ui/tests/providers/**" -> "tests/providers"
TEST_PATHS="${E2E_TEST_PATHS}"
TEST_PATHS="${{ env.E2E_TEST_PATHS }}"
# Remove ui/ prefix and convert ** to empty (playwright handles recursion)
TEST_PATHS=$(echo "$TEST_PATHS" | sed 's|ui/||g' | sed 's|\*\*||g' | tr ' ' '\n' | sort -u)
# Drop auth setup helpers (not runnable test suites)
@@ -251,8 +244,6 @@ jobs:
echo "" >> $GITHUB_STEP_SUMMARY
echo "No UI E2E tests needed for this change." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "Affected modules: \`${NEEDS_IMPACT_ANALYSIS_OUTPUTS_MODULES}\`" >> $GITHUB_STEP_SUMMARY
echo "Affected modules: \`${{ needs.impact-analysis.outputs.modules }}\`" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "To run all tests, modify a file in a critical path (e.g., \`ui/lib/**\`)." >> $GITHUB_STEP_SUMMARY
env:
NEEDS_IMPACT_ANALYSIS_OUTPUTS_MODULES: ${{ needs.impact-analysis.outputs.modules }}

View File

@@ -31,9 +31,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
# zizmor: ignore[artipacked]
persist-credentials: true # Required by tj-actions/changed-files to fetch PR branch
- name: Check for UI changes
id: check-changes
@@ -84,7 +81,7 @@ jobs:
- name: Setup pnpm
if: steps.check-changes.outputs.any_changed == 'true'
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4
uses: pnpm/action-setup@v4
with:
version: 10
run_install: false
@@ -125,12 +122,10 @@ jobs:
if: steps.check-changes.outputs.any_changed == 'true' && steps.critical-changes.outputs.any_changed != 'true' && steps.changed-source.outputs.all_changed_files != ''
run: |
echo "Running tests related to changed files:"
echo "${STEPS_CHANGED_SOURCE_OUTPUTS_ALL_CHANGED_FILES}"
echo "${{ steps.changed-source.outputs.all_changed_files }}"
# Convert space-separated to vitest related format (remove ui/ prefix for relative paths)
CHANGED_FILES=$(echo "${STEPS_CHANGED_SOURCE_OUTPUTS_ALL_CHANGED_FILES}" | tr ' ' '\n' | sed 's|^ui/||' | tr '\n' ' ')
CHANGED_FILES=$(echo "${{ steps.changed-source.outputs.all_changed_files }}" | tr ' ' '\n' | sed 's|^ui/||' | tr '\n' ' ')
pnpm exec vitest related $CHANGED_FILES --run
env:
STEPS_CHANGED_SOURCE_OUTPUTS_ALL_CHANGED_FILES: ${{ steps.changed-source.outputs.all_changed_files }}
- name: Run unit tests (test files only changed)
if: steps.check-changes.outputs.any_changed == 'true' && steps.critical-changes.outputs.any_changed != 'true' && steps.changed-source.outputs.all_changed_files == ''

View File

@@ -6,7 +6,7 @@ LABEL org.opencontainers.image.source="https://github.com/prowler-cloud/prowler"
ARG POWERSHELL_VERSION=7.5.0
ENV POWERSHELL_VERSION=${POWERSHELL_VERSION}
ARG TRIVY_VERSION=0.69.2
ARG TRIVY_VERSION=0.66.0
ENV TRIVY_VERSION=${TRIVY_VERSION}
# hadolint ignore=DL3008

View File

@@ -148,17 +148,21 @@ Prowler App offers flexible installation methods tailored to various environment
**Commands**
``` console
VERSION=$(curl -s https://api.github.com/repos/prowler-cloud/prowler/releases/latest | jq -r .tag_name)
curl -sLO "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/tags/${VERSION}/docker-compose.yml"
# Environment variables can be customized in the .env file. Using default values in production environments is not recommended.
curl -sLO "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/tags/${VERSION}/.env"
curl -LO https://raw.githubusercontent.com/prowler-cloud/prowler/refs/heads/master/docker-compose.yml
curl -LO https://raw.githubusercontent.com/prowler-cloud/prowler/refs/heads/master/.env
docker compose up -d
```
> [!WARNING]
> 🔒 For a secure setup, the API auto-generates a unique key pair, `DJANGO_TOKEN_SIGNING_KEY` and `DJANGO_TOKEN_VERIFYING_KEY`, and stores it in `~/.config/prowler-api` (non-container) or the bound Docker volume in `_data/api` (container). Never commit or reuse static/default keys. To rotate keys, delete the stored key files and restart the API.
> Containers are built for `linux/amd64`.
Once configured, access the Prowler App at http://localhost:3000. Sign up using your email and password to get started.
### Configuring Your Workstation for Prowler App
If your workstation's architecture is incompatible, you can resolve this by:
- **Setting the environment variable**: `DOCKER_DEFAULT_PLATFORM=linux/amd64`
- **Using the following flag in your Docker command**: `--platform linux/amd64`
> Once configured, access the Prowler App at http://localhost:3000. Sign up using your email and password to get started.
### Common Issues with Docker Pull Installation

View File

@@ -2,7 +2,7 @@
All notable changes to the **Prowler API** are documented in this file.
## [1.20.0] (Prowler v5.19.0)
## [1.20.0] (Prowler UNRELEASED)
### 🚀 Added
@@ -17,15 +17,20 @@ All notable changes to the **Prowler API** are documented in this file.
- Attack Paths: Queries definition now has short description and attribution [(#9983)](https://github.com/prowler-cloud/prowler/pull/9983)
- Attack Paths: Internet node is created while scan [(#9992)](https://github.com/prowler-cloud/prowler/pull/9992)
- Attack Paths: Add full paths set from [pathfinding.cloud](https://pathfinding.cloud/) [(#10008)](https://github.com/prowler-cloud/prowler/pull/10008)
- Support CSA CCM 4.0 for the AWS provider [(#10018)](https://github.com/prowler-cloud/prowler/pull/10018)
- Support CSA CCM 4.0 for the GCP provider [(#10042)](https://github.com/prowler-cloud/prowler/pull/10042)
- Support CSA CCM 4.0 for the Azure provider [(#10039)](https://github.com/prowler-cloud/prowler/pull/10039)
- Support CSA CCM 4.0 for the Oracle Cloud provider [(#10057)](https://github.com/prowler-cloud/prowler/pull/10057)
- Support CSA CCM 4.0 for the Alibaba Cloud provider [(#10061)](https://github.com/prowler-cloud/prowler/pull/10061)
- Attack Paths: Mark attack Paths scan as failed when Celery task fails outside job error handling [(#10065)](https://github.com/prowler-cloud/prowler/pull/10065)
- Attack Paths: Remove legacy per-scan `graph_database` and `is_graph_database_deleted` fields from AttackPathsScan model [(#10077)](https://github.com/prowler-cloud/prowler/pull/10077)
- Attack Paths: Add `graph_data_ready` field to decouple query availability from scan state [(#10089)](https://github.com/prowler-cloud/prowler/pull/10089)
- AI agent guidelines with TDD and testing skills references [(#9925)](https://github.com/prowler-cloud/prowler/pull/9925)
- Attack Paths: Upgrade Cartography from fork 0.126.1 to upstream 0.129.0 and Neo4j driver from 5.x to 6.x [(#10110)](https://github.com/prowler-cloud/prowler/pull/10110)
- Attack Paths: Query results now filtered by provider, preventing future cross-tenant and cross-provider data leakage [(#10118)](https://github.com/prowler-cloud/prowler/pull/10118)
- Attack Paths: Add private labels and properties in Attack Paths graphs for avoiding future overlapping with Cartography's ones [(#10124)](https://github.com/prowler-cloud/prowler/pull/10124)
- Attack Paths: Query endpoint executes them in read only mode [(#10140)](https://github.com/prowler-cloud/prowler/pull/10140)
- Attack Paths: `Accept` header query endpoints also accepts `text/plain`, supporting compact plain-text format for LLM consumption [(#10162)](https://github.com/prowler-cloud/prowler/pull/10162)
- Bump Trivy from 0.69.1 to 0.69.2 [(#10210)](https://github.com/prowler-cloud/prowler/pull/10210)
### 🐞 Fixed
@@ -41,7 +46,7 @@ All notable changes to the **Prowler API** are documented in this file.
---
## [1.19.3] (Prowler v5.18.3)
## [1.19.3] (Prowler UNRELEASED)
### 🐞 Fixed

View File

@@ -5,7 +5,7 @@ LABEL maintainer="https://github.com/prowler-cloud/api"
ARG POWERSHELL_VERSION=7.5.0
ENV POWERSHELL_VERSION=${POWERSHELL_VERSION}
ARG TRIVY_VERSION=0.69.2
ARG TRIVY_VERSION=0.69.1
ENV TRIVY_VERSION=${TRIVY_VERSION}
# hadolint ignore=DL3008

397
api/poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,7 +24,7 @@ dependencies = [
"drf-spectacular-jsonapi==0.5.1",
"gunicorn==23.0.0",
"lxml==5.3.2",
"prowler @ git+https://github.com/prowler-cloud/prowler.git@v5.19",
"prowler @ git+https://github.com/prowler-cloud/prowler.git@master",
"psycopg2-binary==2.9.9",
"pytest-celery[redis] (>=1.0.1,<2.0.0)",
"sentry-sdk[django] (>=2.20.0,<3.0.0)",

View File

@@ -99,7 +99,7 @@
},
"user-guide/tutorials/prowler-app-rbac",
"user-guide/tutorials/prowler-app-api-keys",
"user-guide/tutorials/prowler-app-import-findings",
"user-guide/tutorials/prowler-app-findings-ingestion",
{
"group": "Mutelist",
"expanded": true,
@@ -117,13 +117,6 @@
"user-guide/tutorials/prowler-app-jira-integration"
]
},
{
"group": "AWS Organizations",
"expanded": true,
"pages": [
"user-guide/tutorials/prowler-cloud-aws-organizations"
]
},
{
"group": "Lighthouse AI",
"pages": [
@@ -131,7 +124,6 @@
"user-guide/tutorials/prowler-app-lighthouse-multi-llm"
]
},
"user-guide/tutorials/prowler-app-attack-paths",
"user-guide/tutorials/prowler-cloud-public-ips",
{
"group": "Tutorials",

View File

@@ -23,15 +23,9 @@ Refer to the [Prowler App Tutorial](/user-guide/tutorials/prowler-app) for detai
```bash
VERSION=$(curl -s https://api.github.com/repos/prowler-cloud/prowler/releases/latest | jq -r .tag_name)
curl -sLO "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/tags/${VERSION}/docker-compose.yml"
# Environment variables can be customized in the .env file. Using default values in production environments is not recommended.
curl -sLO "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/tags/${VERSION}/.env"
docker compose up -d
```
<Callout icon="lock" iconType="regular" color="#e74c3c">
For a secure setup, the API auto-generates a unique key pair, `DJANGO_TOKEN_SIGNING_KEY` and `DJANGO_TOKEN_VERIFYING_KEY`, and stores it in `~/.config/prowler-api` (non-container) or the bound Docker volume in `_data/api` (container). Never commit or reuse static/default keys. To rotate keys, delete the stored key files and restart the API.
</Callout>
</Tab>
<Tab title="GitHub">
_Requirements_:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -1,71 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 420" font-family="'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif">
<defs>
<filter id="shadow" x="-4%" y="-4%" width="108%" height="108%">
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-opacity="0.08"/>
</filter>
</defs>
<!-- Title -->
<text x="550" y="40" text-anchor="middle" font-size="22" font-weight="700" fill="#4285F4">Onboarding Flow</text>
<!-- Step 1 -->
<rect x="30" y="70" width="220" height="220" rx="12" fill="#fff" stroke="#4285F4" stroke-width="2.5" stroke-dasharray="8 4" filter="url(#shadow)"/>
<circle cx="140" cy="100" r="22" fill="#4285F4"/>
<text x="140" y="107" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">1</text>
<text x="140" y="145" text-anchor="middle" font-size="15" font-weight="700" fill="#1a1a2e">Create Management</text>
<text x="140" y="165" text-anchor="middle" font-size="15" font-weight="700" fill="#1a1a2e">Account Role</text>
<rect x="80" y="185" width="120" height="24" rx="12" fill="#E8F0FE"/>
<text x="140" y="201" text-anchor="middle" font-size="11" font-weight="600" fill="#4285F4">Manually in IAM</text>
<text x="140" y="232" text-anchor="middle" font-size="12" fill="#5f6368">Allows Prowler to</text>
<text x="140" y="248" text-anchor="middle" font-size="12" fill="#5f6368">discover your org</text>
<text x="140" y="264" text-anchor="middle" font-size="12" fill="#5f6368">structure</text>
<!-- Arrow 1→2 -->
<path d="M260 180 L290 180" stroke="#9aa0a6" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#9aa0a6"/>
</marker>
</defs>
<!-- Step 2 -->
<rect x="300" y="70" width="220" height="220" rx="12" fill="#fff" stroke="#7B61FF" stroke-width="2.5" filter="url(#shadow)"/>
<circle cx="410" cy="100" r="22" fill="#7B61FF"/>
<text x="410" y="107" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">2</text>
<text x="410" y="145" text-anchor="middle" font-size="15" font-weight="700" fill="#1a1a2e">Deploy StackSet</text>
<rect x="340" y="165" width="140" height="24" rx="12" fill="#F3F0FF"/>
<text x="410" y="181" text-anchor="middle" font-size="11" font-weight="600" fill="#7B61FF">In AWS Console</text>
<text x="410" y="212" text-anchor="middle" font-size="12" fill="#5f6368">Creates ProwlerScan</text>
<text x="410" y="228" text-anchor="middle" font-size="12" fill="#5f6368">role in every</text>
<text x="410" y="244" text-anchor="middle" font-size="12" fill="#5f6368">member account</text>
<!-- Arrow 2→3 -->
<path d="M530 180 L560 180" stroke="#9aa0a6" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<!-- Step 3 -->
<rect x="570" y="70" width="220" height="220" rx="12" fill="#fff" stroke="#00BFA5" stroke-width="2.5" filter="url(#shadow)"/>
<circle cx="680" cy="100" r="22" fill="#00BFA5"/>
<text x="680" y="107" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">3</text>
<text x="680" y="145" text-anchor="middle" font-size="15" font-weight="700" fill="#1a1a2e">Run the Wizard</text>
<rect x="615" y="165" width="130" height="24" rx="12" fill="#E0F7F4"/>
<text x="680" y="181" text-anchor="middle" font-size="11" font-weight="600" fill="#00BFA5">In Prowler Cloud</text>
<text x="680" y="212" text-anchor="middle" font-size="12" fill="#5f6368">Discovers accounts,</text>
<text x="680" y="228" text-anchor="middle" font-size="12" fill="#5f6368">tests connections</text>
<!-- Arrow 3→4 -->
<path d="M800 180 L830 180" stroke="#9aa0a6" stroke-width="2" fill="none" marker-end="url(#arrowhead)"/>
<!-- Step 4 -->
<rect x="840" y="70" width="220" height="220" rx="12" fill="#fff" stroke="#F9AB00" stroke-width="2.5" filter="url(#shadow)"/>
<circle cx="950" cy="100" r="22" fill="#F9AB00"/>
<text x="950" y="107" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">4</text>
<text x="950" y="145" text-anchor="middle" font-size="15" font-weight="700" fill="#1a1a2e">Launch Scans</text>
<rect x="898" y="165" width="104" height="24" rx="12" fill="#FEF7E0"/>
<text x="950" y="181" text-anchor="middle" font-size="11" font-weight="600" fill="#F9AB00">Automatic</text>
<text x="950" y="212" text-anchor="middle" font-size="12" fill="#5f6368">Scans run on all</text>
<text x="950" y="228" text-anchor="middle" font-size="12" fill="#5f6368">connected accounts</text>
<text x="950" y="244" text-anchor="middle" font-size="12" fill="#5f6368">on your schedule</text>
<!-- Footer -->
<text x="550" y="340" text-anchor="middle" font-size="13" fill="#9aa0a6">Steps 1 and 2 are done once in AWS | Steps 3 and 4 are done in Prowler Cloud</text>
</svg>

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

View File

@@ -1,96 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 520" font-family="'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif">
<defs>
<filter id="shadow" x="-4%" y="-4%" width="108%" height="108%">
<feDropShadow dx="0" dy="2" stdDeviation="4" flood-opacity="0.08"/>
</filter>
<linearGradient id="mgmtHeader" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#4285F4"/>
<stop offset="100%" stop-color="#5E97F6"/>
</linearGradient>
<linearGradient id="memberHeader" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="#00BFA5"/>
<stop offset="100%" stop-color="#1DE9B6"/>
</linearGradient>
</defs>
<!-- Title -->
<text x="550" y="36" text-anchor="middle" font-size="22" font-weight="700" fill="#4285F4">Two Roles Architecture</text>
<!-- ===== Management Account Card ===== -->
<rect x="30" y="60" width="440" height="380" rx="14" fill="#fff" stroke="#4285F4" stroke-width="2" filter="url(#shadow)"/>
<!-- Header bar -->
<rect x="30" y="60" width="440" height="44" rx="14" fill="url(#mgmtHeader)"/>
<rect x="30" y="90" width="440" height="14" fill="url(#mgmtHeader)"/>
<text x="250" y="88" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">Management Account</text>
<!-- Inner card -->
<rect x="50" y="118" width="400" height="300" rx="10" fill="#F0F4FF" stroke="#C5D6F7" stroke-width="1"/>
<text x="250" y="148" text-anchor="middle" font-size="15" font-weight="700" fill="#4285F4">Management Role</text>
<!-- Purpose -->
<text x="70" y="178" font-size="13" font-weight="700" fill="#1a1a2e">Purpose:</text>
<text x="70" y="196" font-size="12" fill="#5f6368">Discover Organization structure + scan management account</text>
<!-- Permissions -->
<text x="70" y="222" font-size="13" font-weight="700" fill="#1a1a2e">Permissions:</text>
<text x="82" y="240" font-size="11" fill="#5f6368">SecurityAudit (AWS managed policy)</text>
<text x="82" y="256" font-size="11" fill="#5f6368">ViewOnlyAccess (AWS managed policy)</text>
<text x="82" y="272" font-size="11" fill="#5f6368">Additional read-only (inline policy)</text>
<text x="82" y="288" font-size="11" fill="#4285F4" font-weight="600">organizations:DescribeAccount</text>
<text x="82" y="304" font-size="11" fill="#4285F4" font-weight="600">organizations:DescribeOrganization</text>
<text x="82" y="320" font-size="11" fill="#4285F4" font-weight="600">organizations:ListAccounts</text>
<text x="82" y="336" font-size="11" fill="#4285F4" font-weight="600">organizations:ListAccountsForParent</text>
<text x="82" y="352" font-size="11" fill="#4285F4" font-weight="600">organizations:ListOrganizationalUnitsForParent</text>
<text x="82" y="368" font-size="11" fill="#4285F4" font-weight="600">organizations:ListRoots</text>
<text x="82" y="384" font-size="11" fill="#4285F4" font-weight="600">organizations:ListTagsForResource</text>
<!-- Deploy badge -->
<rect x="145" y="400" width="210" height="28" rx="14" fill="#FFF3E0" stroke="#F9AB00" stroke-width="1.5"/>
<text x="250" y="419" text-anchor="middle" font-size="12" font-weight="700" fill="#E65100">Deploy: MANUALLY in IAM Console</text>
<!-- ===== Prowler Cloud connector ===== -->
<rect x="490" y="195" width="120" height="36" rx="8" fill="#F5F5F5" stroke="#E0E0E0" stroke-width="1"/>
<text x="550" y="218" text-anchor="middle" font-size="12" font-weight="600" fill="#5f6368">Prowler Cloud</text>
<!-- Connector lines -->
<line x1="490" y1="213" x2="470" y2="213" stroke="#9aa0a6" stroke-width="1.5" stroke-dasharray="4 3"/>
<line x1="610" y1="213" x2="630" y2="213" stroke="#9aa0a6" stroke-width="1.5" stroke-dasharray="4 3"/>
<!-- ===== Member Accounts Card ===== -->
<rect x="630" y="60" width="440" height="380" rx="14" fill="#fff" stroke="#00BFA5" stroke-width="2" filter="url(#shadow)"/>
<!-- Header bar -->
<rect x="630" y="60" width="440" height="44" rx="14" fill="url(#memberHeader)"/>
<rect x="630" y="90" width="440" height="14" fill="url(#memberHeader)"/>
<text x="850" y="88" text-anchor="middle" font-size="16" font-weight="700" fill="#fff">Member Accounts</text>
<!-- Inner card -->
<rect x="650" y="118" width="400" height="300" rx="10" fill="#E8F8F5" stroke="#B2DFDB" stroke-width="1"/>
<text x="850" y="148" text-anchor="middle" font-size="15" font-weight="700" fill="#00897B">ProwlerScan Role (per account)</text>
<!-- Purpose -->
<text x="670" y="178" font-size="13" font-weight="700" fill="#1a1a2e">Purpose:</text>
<text x="670" y="196" font-size="12" fill="#5f6368">Security scanning of each account</text>
<!-- Permissions -->
<text x="670" y="222" font-size="13" font-weight="700" fill="#1a1a2e">Permissions:</text>
<text x="682" y="240" font-size="11" fill="#5f6368">SecurityAudit (AWS managed policy)</text>
<text x="682" y="256" font-size="11" fill="#5f6368">ViewOnlyAccess (AWS managed policy)</text>
<text x="682" y="272" font-size="11" fill="#5f6368">Additional read-only (inline policy)</text>
<!-- Scope -->
<text x="670" y="302" font-size="13" font-weight="700" fill="#1a1a2e">Scope:</text>
<text x="682" y="320" font-size="12" fill="#5f6368">Read-only access across all AWS services</text>
<text x="682" y="338" font-size="12" fill="#5f6368">No write or modify permissions</text>
<!-- Deploy badge -->
<rect x="735" y="400" width="230" height="28" rx="14" fill="#E8F5E9" stroke="#66BB6A" stroke-width="1.5"/>
<text x="850" y="419" text-anchor="middle" font-size="12" font-weight="700" fill="#2E7D32">Deploy: via CloudFormation StackSet</text>
<!-- Footer labels -->
<text x="250" y="478" text-anchor="middle" font-size="14" font-weight="700" fill="#4285F4">Prowler discovers</text>
<text x="250" y="496" text-anchor="middle" font-size="12" fill="#5f6368">your org structure</text>
<text x="850" y="478" text-anchor="middle" font-size="14" font-weight="700" fill="#00BFA5">Prowler scans each</text>
<text x="850" y="496" text-anchor="middle" font-size="12" fill="#5f6368">account for findings</text>
</svg>

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 304 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 575 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 275 KiB

View File

@@ -1,2 +0,0 @@
// Reo tracking beacon
!function(){var e,t,n;e="1fca1c3c1571b22",t=function(){Reo.init({clientID:"1fca1c3c1571b22"})},(n=document.createElement("script")).src="https://static.reo.dev/"+e+"/reo.js",n.defer=!0,n.onload=t,document.head.appendChild(n)}();

View File

@@ -16,33 +16,23 @@ Prowler requires Alibaba Cloud credentials to perform security checks. Authentic
### Credentials URI (Recommended for Centralized Services)
Prowler can retrieve credentials from an external URI endpoint. Provide the URI via the `--credentials-uri` flag or the `ALIBABA_CLOUD_CREDENTIALS_URI` environment variable. The URI must return credentials in the standard JSON format.
If `--credentials-uri` is provided (or `ALIBABA_CLOUD_CREDENTIALS_URI` environment variable), Prowler will retrieve credentials from the specified external URI endpoint. The URI must return credentials in the standard JSON format.
```bash
# Using CLI flag
prowler alibabacloud --credentials-uri http://localhost:8080/credentials
# Or using environment variable
export ALIBABA_CLOUD_CREDENTIALS_URI="http://localhost:8080/credentials"
prowler alibabacloud
```
### OIDC Role Authentication (Recommended for ACK/Kubernetes)
OIDC authentication assumes the specified role using an OIDC token. This is the most secure method for containerized applications running in ACK (Alibaba Container Service for Kubernetes) with RRSA enabled.
The role ARN can be provided via the `--oidc-role-arn` flag or the `ALIBABA_CLOUD_ROLE_ARN` environment variable. The OIDC provider ARN and token file must be set via environment variables:
If OIDC environment variables are set, Prowler will use OIDC authentication to assume the specified role. This is the most secure method for containerized applications running in ACK (Alibaba Container Service for Kubernetes) with RRSA enabled.
Required environment variables:
- `ALIBABA_CLOUD_ROLE_ARN`
- `ALIBABA_CLOUD_OIDC_PROVIDER_ARN`
- `ALIBABA_CLOUD_OIDC_TOKEN_FILE`
```bash
# Using CLI flag for role ARN
export ALIBABA_CLOUD_OIDC_PROVIDER_ARN="acs:ram::123456789012:oidc-provider/ack-rrsa-provider"
export ALIBABA_CLOUD_OIDC_TOKEN_FILE="/var/run/secrets/tokens/oidc-token"
prowler alibabacloud --oidc-role-arn acs:ram::123456789012:role/YourRole
# Or using all environment variables
export ALIBABA_CLOUD_ROLE_ARN="acs:ram::123456789012:role/YourRole"
export ALIBABA_CLOUD_OIDC_PROVIDER_ARN="acs:ram::123456789012:oidc-provider/ack-rrsa-provider"
export ALIBABA_CLOUD_OIDC_TOKEN_FILE="/var/run/secrets/tokens/oidc-token"
@@ -64,17 +54,9 @@ prowler alibabacloud
### RAM Role Assumption (Recommended for Cross-Account)
For cross-account access, use RAM role assumption. Provide the initial credentials (access keys) via environment variables and the target role ARN via the `--role-arn` flag or the `ALIBABA_CLOUD_ROLE_ARN` environment variable.
The `--role-session-name` flag customizes the session identifier (defaults to `ProwlerAssessmentSession`).
For cross-account access, use RAM role assumption. You must provide the initial credentials (access keys) and the target role ARN.
```bash
# Using CLI flags
export ALIBABA_CLOUD_ACCESS_KEY_ID="your-access-key-id"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="your-access-key-secret"
prowler alibabacloud --role-arn acs:ram::123456789012:role/ProwlerAuditRole --role-session-name MyAuditSession
# Or using all environment variables
export ALIBABA_CLOUD_ACCESS_KEY_ID="your-access-key-id"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="your-access-key-secret"
export ALIBABA_CLOUD_ROLE_ARN="acs:ram::123456789012:role/ProwlerAuditRole"

View File

@@ -117,12 +117,6 @@ prowler alibabacloud
#### RAM Role Assumption
```bash
# Using --role-arn CLI flag
export ALIBABA_CLOUD_ACCESS_KEY_ID="your-access-key-id"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="your-access-key-secret"
prowler alibabacloud --role-arn acs:ram::123456789012:role/ProwlerAuditRole
# Or using environment variables
export ALIBABA_CLOUD_ACCESS_KEY_ID="your-access-key-id"
export ALIBABA_CLOUD_ACCESS_KEY_SECRET="your-access-key-secret"
export ALIBABA_CLOUD_ROLE_ARN="acs:ram::123456789012:role/ProwlerAuditRole"

View File

@@ -2,12 +2,6 @@
title: 'AWS Organizations in Prowler'
---
<Info>
**Using Prowler Cloud?** You can onboard your entire AWS Organization through the UI with automatic account discovery, OU-aware tree selection, and bulk connection testing — no scripts or YAML files required.
See [AWS Organizations in Prowler Cloud](/user-guide/tutorials/prowler-cloud-aws-organizations) for the full walkthrough.
</Info>
Prowler can integrate with AWS Organizations to manage the visibility and onboarding of accounts centrally.
When trusted access is enabled with the Organization, Prowler can discover accounts as they are created and even automate deployment of the Prowler Scan IAM Role.

View File

@@ -135,16 +135,3 @@ prowler gcp --impersonate-service-account <service-account-email>
```
More details on authentication methods in the [Authentication](/user-guide/providers/gcp/authentication) page.
### Skip API Check
By default, Prowler verifies which Google Cloud APIs are enabled before running checks for each service. To skip this verification and assume all APIs are active, use the `--skip-api-check` flag:
```console
prowler gcp --skip-api-check
```
<Note>
This is useful when the authenticated principal lacks the `serviceusage.services.list` permission but has access to individual service APIs.
</Note>

View File

@@ -135,7 +135,7 @@ prowler iac --scan-path ./my-iac-directory --scanners vuln misconfig
#### Exclude Paths
```sh
prowler iac --scan-path ./my-iac-directory --exclude-path ./my-iac-directory/test ./my-iac-directory/examples
prowler iac --scan-path ./my-iac-directory --exclude-path ./my-iac-directory/test,./my-iac-directory/examples
```
### Output

View File

@@ -127,18 +127,4 @@ Include PowerShell module initialization to run every check:
prowler m365 --sp-env-auth --init-modules
```
### Region Selection
By default, Prowler connects to the global Microsoft 365 environment (`M365Global`). To target a different cloud environment, use the `--region` flag:
```console
prowler m365 --sp-env-auth --region M365USGovernment
```
Available regions:
* **M365Global** (default): Standard commercial cloud
* **M365China**: China-operated cloud (21Vianet)
* **M365USGovernment**: US Government cloud (GCC High)
---

View File

@@ -7,11 +7,9 @@ Prowler offers an automated tool to discover and provision all AWS accounts with
The tool, `aws_org_generator.py`, complements the [Bulk Provider Provisioning](./bulk-provider-provisioning) tool and is available in the Prowler repository at: [util/prowler-bulk-provisioning](https://github.com/prowler-cloud/prowler/tree/master/util/prowler-bulk-provisioning)
<Note>
**Native AWS Organizations support is now available in Prowler Cloud.** You can onboard all accounts via the UI wizard — with automatic discovery, hierarchical tree selection, connection testing, and bulk scan launch — without any scripts or YAML files.
Native support for bulk provisioning AWS Organizations and similar multi-account structures directly in the Prowler UI/API is on the official roadmap.
See [AWS Organizations in Prowler Cloud](/user-guide/tutorials/prowler-cloud-aws-organizations).
The CLI-based tool below remains useful for self-hosted Prowler App and advanced automation scenarios.
Track progress and vote for this feature at: [Bulk Provisioning in the UI/API for AWS Organizations](https://roadmap.prowler.com/p/builk-provisioning-in-the-uiapi-for-aws-organizations-and-alike)
</Note>
{/* TODO: Add screenshot of the tool in action */}

View File

@@ -1,203 +0,0 @@
---
title: "Attack Paths"
description: "Identify privilege escalation chains and security misconfigurations across cloud environments using graph-based analysis."
---
import { VersionBadge } from "/snippets/version-badge.mdx"
<VersionBadge version="5.17.0" />
Attack Paths analyzes relationships between cloud resources, permissions, and security findings to detect how privileges can be escalated and how misconfigurations can be exploited by threat actors.
By mapping these relationships as a graph, Attack Paths reveals risks that individual security checks cannot detect on their own — such as an IAM role that can escalate its own permissions, or a chain of policies that grants unintended access to sensitive resources.
<Note>
Attack Paths is currently available for **AWS** providers. Support for
additional providers is planned.
</Note>
## Prerequisites
The following prerequisites are required for Attack Paths:
- **An AWS provider is configured** with valid credentials in Prowler App. For setup instructions, see [Getting Started with AWS](/user-guide/providers/aws/getting-started-aws).
- **At least one scan has completed** on the configured AWS provider. Attack Paths scans run automatically alongside regular security scans — no separate configuration is required.
## How Attack Paths Scans Work
Attack Paths scans are generated automatically when a security scan runs on an AWS provider. Each completed scan produces graph data that maps relationships between IAM principals, policies, trust configurations, and other resources.
Once the scan finishes and the graph data is ready, the scan appears in the Attack Paths scan table with a **Completed** status. Scans that are still processing display as **Executing** or **Scheduled**.
<Note>
Since Prowler scans all configured providers every **24 hours** by default,
Attack Paths data stays up to date automatically.
</Note>
## Accessing Attack Paths
To open Attack Paths, click **Attack Paths** in the left navigation menu.
<img
src="/images/prowler-app/attack-paths/navigation.png"
alt="Attack Paths navigation menu entry"
width="700"
/>
The main interface is divided into two areas:
- **Left panel:** A table listing all available Attack Paths scans
- **Right panel:** The query selector, parameter form, and execute controls
## Selecting a Scan
The scans table displays all Attack Paths scans with the following columns:
- **Provider / Account:** The AWS provider alias and account identifier
- **Last scan date:** When the scan completed
- **Status:** Current state of the scan (Completed, Executing, Scheduled, or Failed)
- **Progress:** Completion percentage for in-progress scans
- **Duration:** Total scan time
To select a scan for analysis, click **Select** on any row with a **Completed** status.
<img
src="/images/prowler-app/attack-paths/scan-list-table.png"
alt="Attack Paths scan list table showing completed scans"
width="700"
/>
<Note>
Only scans with a **Completed** status and ready graph data can be selected.
Scans that are still executing or have failed appear with disabled action
buttons.
</Note>
## Choosing a Query
After selecting a scan, the right panel activates a query dropdown. Each query targets a specific type of privilege escalation or misconfiguration pattern.
To choose a query, click the dropdown and select from the available options. Each option displays:
- **Query name:** A descriptive title (e.g., "IAM Privilege Escalation via AssumeRole")
- **Short description:** A brief summary of what the query detects
<img
src="/images/prowler-app/attack-paths/query-selector.png"
alt="Attack Paths query selector dropdown showing available queries"
width="700"
/>
Once selected, a description card appears below the dropdown with additional context about the query, including attribution links to external references when available.
## Configuring Query Parameters
Some queries accept optional or required parameters to narrow the scope of the analysis. When a query has parameters, a dynamic form appears below the query description.
- **Required fields** are marked with an asterisk (\*) and must be filled before executing
- **Optional fields** refine the query results but are not mandatory
If a query requires no parameters, the form displays a message confirming that the query is ready to execute.
<img
src="/images/prowler-app/attack-paths/query-parameters.png"
alt="Attack Paths query parameter form with fields"
width="700"
/>
## Executing a Query
To run the selected query against the scan data, click **Execute Query**. The button displays a loading state while the query processes.
If the query returns no results, an informational message appears. Common reasons include:
- **No matching patterns found:** The scanned environment does not contain the privilege escalation chain the query targets
- **Insufficient permissions:** The scan credentials may not have captured all the data the query needs
<img
src="/images/prowler-app/attack-paths/execute-query.png"
alt="Attack Paths right panel with query selected and execute button"
width="700"
/>
## Exploring the Graph
After a successful execution, the graph visualization renders below the query builder in a full-width panel. The graph maps relationships between cloud resources, IAM entities, and security findings.
### Node Types
- **Resource nodes** (rounded pills): Represent cloud resources such as IAM roles, policies, EC2 instances, and S3 buckets. Each resource type has a distinct color.
- **Finding nodes** (hexagons): Represent Prowler security findings linked to resources in the graph. Colors indicate severity level (critical, high, medium, low).
### Edge Types
- **Solid lines:** Direct relationships between resources (e.g., a role attached to a policy)
- **Dashed lines:** Connections between resources and their associated findings
A **legend** at the bottom of the graph lists all node types and edge types present in the current view.
<img
src="/images/prowler-app/attack-paths/graph-visualization.png"
alt="Attack Paths graph showing nodes, edges, and legend"
width="700"
/>
## Interacting with the Graph
### Filtering by Node
Click any node in the graph to filter the view and display only paths that pass through that node. When a filter is active:
- An information banner shows which node is selected
- Click **Back to Full View** to restore the complete graph
<img
src="/images/prowler-app/attack-paths/graph-filtered.png"
alt="Attack Paths graph filtered to show paths through a selected node"
width="700"
/>
### Graph Controls
The toolbar in the top-right corner of the graph provides:
- **Zoom in / Zoom out:** Adjust the zoom level
- **Fit to screen:** Reset the view to fit all nodes
- **Export:** Download the current graph as an SVG file
- **Fullscreen:** Open the graph in a full-screen modal with a side-by-side node detail panel
<Note>
Use **Ctrl + Scroll** (or **Cmd + Scroll** on macOS) to zoom directly within
the graph area.
</Note>
## Viewing Node Details
Click any node to open the **Node Details** panel below the graph. This panel displays:
- **Node type:** The resource category (e.g., "IAM Role," "EC2 Instance")
- **Properties:** All attributes of the selected node, including identifiers, timestamps, and configuration details
- **Related findings** (for resource nodes): A list of Prowler findings linked to the resource, with severity, title, and status
- **Affected resources** (for finding nodes): A list of resources associated with the finding
For finding nodes, a "View Finding" button links directly to the finding detail page for further investigation.
<img
src="/images/prowler-app/attack-paths/node-details.png"
alt="Attack Paths node detail panel showing properties and related findings"
width="700"
/>
## Fullscreen Mode
To expand the graph for detailed exploration, click the fullscreen icon in the graph toolbar. The fullscreen modal provides:
- The full graph visualization with all zoom and export controls
- A side panel for node details that appears when a node is selected
- All filtering and interaction capabilities available in the standard view
<img
src="/images/prowler-app/attack-paths/fullscreen-mode.png"
alt="Attack Paths fullscreen mode with graph and node detail side panel"
width="700"
/>

View File

@@ -1,5 +1,5 @@
---
title: 'Import Findings'
title: 'Findings Ingestion'
description: 'Upload OCSF scan results to Prowler Cloud from external sources or the CLI'
---
@@ -10,7 +10,7 @@ import { VersionBadge } from "/snippets/version-badge.mdx"
Findings Ingestion enables uploading OCSF (Open Cybersecurity Schema Framework) scan results to Prowler Cloud. This feature supports importing findings from Prowler CLI output files that use the [Detection Finding](https://schema.ocsf.io/classes/detection_finding) class.
<Note>
This feature is available exclusively in **Prowler Cloud** with a paid subscription.
This feature is available exclusively in **Prowler Cloud**.
</Note>
## OCSF Detection Finding format
@@ -132,77 +132,69 @@ Only **Detection Finding** (`class_uid: 2004`) records are accepted. Other OCSF
## Required permissions
The **Manage Ingestions** RBAC permission controls access to the ingestion endpoints. Without this permission, findings cannot be submitted via the API or `--push-to-cloud`.
The **Manage Ingestions** RBAC permission controls access to the ingestion endpoints. Without this permission, findings cannot be submitted via the API or `--export-ocsf`.
For more information about RBAC permissions, refer to the [Prowler App RBAC documentation](/user-guide/tutorials/prowler-app-rbac).
## Using the CLI
The `--push-to-cloud` flag uploads scan results directly to Prowler Cloud after a scan completes. This approach automates the ingestion process without manual file uploads.
The `--export-ocsf` flag uploads scan results directly to Prowler Cloud after a scan completes. This approach automates the ingestion process without manual file uploads.
### Prerequisites
- A valid Prowler Cloud API key (see [API Keys](/user-guide/tutorials/prowler-app-api-keys))
- The `PROWLER_CLOUD_API_KEY` environment variable configured
- The `PROWLER_API_KEY` environment variable configured
### Basic usage
```bash
export PROWLER_CLOUD_API_KEY="pk_your_api_key_here"
export PROWLER_API_KEY="pk_your_api_key_here"
prowler aws --push-to-cloud
prowler aws --export-ocsf
```
### Combining with output formats
When using `--push-to-cloud` with custom output formats that exclude OCSF, Prowler generates a temporary OCSF file for upload:
When using `--export-ocsf` with custom output formats that exclude OCSF, Prowler generates a temporary OCSF file for upload:
The temporary OCSF file is saved in the system temporary directory and not in the output path passed with `-o`.
```bash
prowler aws --services accessanalyzer -M csv --push-to-cloud -o /tmp/scan-output
prowler aws --services accessanalyzer -M csv --export-ocsf -o /tmp/scan-output
```
When default output formats include OCSF, Prowler reuses the existing file. Default output formats include JSON-OCSF:
```bash
prowler aws --services accessanalyzer --push-to-cloud -o /tmp/scan-output
prowler aws --services accessanalyzer --export-ocsf -o /tmp/scan-output
```
### CLI output examples
**Successful upload:**
```
Pushing findings to Prowler Cloud, please wait...
Exporting OCSF to Prowler Cloud, please wait...
Findings successfully pushed to Prowler Cloud. Ingestion job: fa8bc8c5-4925-46a0-9fe0-f6575905e094
See more details here: https://cloud.prowler.com/scans
OCSF export accepted. Ingestion job: fa8bc8c5-4925-46a0-9fe0-f6575905e094
```
**Missing API key:**
```
Push to Prowler Cloud skipped: no API key configured. Set the PROWLER_CLOUD_API_KEY
WARNING: OCSF export skipped: no API key configured. Set the PROWLER_API_KEY
environment variable to enable it. Scan results were saved to
/tmp/scan-output/prowler-output-123456789012-20260217131755.ocsf.json
```
**API unreachable:**
```
Push to Prowler Cloud failed: could not reach the Prowler Cloud API at
WARNING: OCSF export skipped: could not reach the Prowler Cloud API at
https://api.prowler.com. Check the URL and your network connection. Scan results
were saved to /tmp/scan-output/prowler-output-123456789012-20260217131755.ocsf.json
```
**No subscription:**
```
Push to Prowler Cloud failed: this feature is only available with a Prowler Cloud
subscription. Scan results were saved to
/tmp/scan-output/prowler-output-123456789012-20260217131755.ocsf.json
```
**Invalid API key:**
```
Push to Prowler Cloud failed: the API returned HTTP 401. Verify your API key is
WARNING: OCSF export failed: the API returned HTTP 401. Verify your API key is
valid and has the right permissions. Scan results were saved to
/tmp/scan-output/prowler-output-123456789012-20260217131755.ocsf.json
```
@@ -220,10 +212,10 @@ The Ingestion API provides endpoints for submitting OCSF files and monitoring jo
Include the API key in the `Authorization` header:
```bash
export PROWLER_CLOUD_API_KEY="pk_your_api_key_here"
export PROWLER_API_KEY="pk_your_api_key_here"
curl -X POST \
-H "Authorization: Api-Key ${PROWLER_CLOUD_API_KEY}" \
-H "Authorization: Api-Key ${PROWLER_API_KEY}" \
-F "file=@/path/to/findings.ocsf.json" \
https://api.prowler.com/api/v1/ingestions
```
@@ -237,7 +229,7 @@ Upload a `.ocsf.json` file containing a JSON array of OCSF Detection Finding rec
**Request:**
```bash
curl -X POST \
-H "Authorization: Api-Key ${PROWLER_CLOUD_API_KEY}" \
-H "Authorization: Api-Key ${PROWLER_API_KEY}" \
-F "file=@scan-results.ocsf.json" \
https://api.prowler.com/api/v1/ingestions
```
@@ -275,7 +267,7 @@ Monitor the progress of an ingestion job.
**Request:**
```bash
curl -X GET \
-H "Authorization: Api-Key ${PROWLER_CLOUD_API_KEY}" \
-H "Authorization: Api-Key ${PROWLER_API_KEY}" \
-H "Accept: application/vnd.api+json" \
https://api.prowler.com/api/v1/ingestions/3650fef9-8e5f-4808-a95f-74f0afae8499
```
@@ -327,7 +319,7 @@ Retrieve a list of ingestion jobs for the tenant.
**Request:**
```bash
curl -X GET \
-H "Authorization: Api-Key ${PROWLER_CLOUD_API_KEY}" \
-H "Authorization: Api-Key ${PROWLER_API_KEY}" \
-H "Accept: application/vnd.api+json" \
"https://api.prowler.com/api/v1/ingestions?filter[status]=completed&page[size]=10"
```
@@ -341,7 +333,7 @@ Retrieve error details for a specific ingestion job.
**Request:**
```bash
curl -X GET \
-H "Authorization: Api-Key ${PROWLER_CLOUD_API_KEY}" \
-H "Authorization: Api-Key ${PROWLER_API_KEY}" \
-H "Accept: application/vnd.api+json" \
https://api.prowler.com/api/v1/ingestions/3650fef9-8e5f-4808-a95f-74f0afae8499/errors
```
@@ -371,9 +363,9 @@ Prowler must be installed in the CI/CD environment before running scans. Refer t
- name: Run Prowler and upload to Cloud
env:
PROWLER_CLOUD_API_KEY: ${{ secrets.PROWLER_CLOUD_API_KEY }}
PROWLER_API_KEY: ${{ secrets.PROWLER_API_KEY }}
run: |
prowler aws --services s3,iam --push-to-cloud
prowler aws --services s3,iam --export-ocsf
```
### GitLab CI
@@ -382,41 +374,13 @@ Prowler must be installed in the CI/CD environment before running scans. Refer t
prowler_scan:
script:
- pip install prowler
- prowler aws --services s3,iam --push-to-cloud
- prowler aws --services s3,iam --export-ocsf
variables:
PROWLER_CLOUD_API_KEY: $PROWLER_CLOUD_API_KEY
PROWLER_API_KEY: $PROWLER_API_KEY
```
## Billing impact
Each unique cloud account discovered in ingested OCSF findings counts as one **provider** in the Prowler Cloud subscription.
- **Existing providers**: If a cloud account was already connected as a provider, findings ingested for that account do **not** incur additional billing. The existing provider is reused.
- **New accounts**: Ingesting findings from accounts not yet connected to Prowler Cloud will result in new providers being created and counted toward the subscription.
- **High-volume ingestion**: Importing findings from many different cloud accounts will create a provider for each account. Review plan limits before large-scale ingestion.
- **Deleted providers**: Removing a provider no longer counts toward the subscription.
For pricing details, see [Prowler Cloud Pricing](https://prowler.com/pricing).
## Troubleshooting
### "Push to Prowler Cloud skipped: no API key configured"
- Set the `PROWLER_CLOUD_API_KEY` environment variable before running the scan
- Verify the variable is exported and not empty
### "Push to Prowler Cloud failed: could not reach the Prowler Cloud API"
- Verify network connectivity to `api.prowler.com`
- Check firewall rules allow outbound HTTPS traffic
- Confirm the API endpoint is not blocked by proxy settings
- If using a custom base URL via `PROWLER_CLOUD_API_BASE_URL`, verify it is correct
### "Push to Prowler Cloud failed: this feature is only available with a Prowler Cloud subscription"
- The API returned HTTP 402, meaning your tenant does not have an active subscription
- Visit [Prowler Cloud Pricing](https://prowler.com/pricing) to review available plans
### HTTP 401 Unauthorized
- Verify the API key is valid and not revoked
@@ -433,3 +397,9 @@ For pricing details, see [Prowler Cloud Pricing](https://prowler.com/pricing).
- Check the `/api/v1/ingestions/{id}/errors` endpoint for details
- Verify the OCSF file format is valid
- Ensure the file contains Detection Finding records
### CLI reports "could not reach the Prowler Cloud API"
- Verify network connectivity to `api.prowler.com`
- Check firewall rules allow outbound HTTPS traffic
- Confirm the API endpoint is not blocked by proxy settings

View File

@@ -238,6 +238,6 @@ To grant all administrative permissions, select the **Grant all admin permission
The following permissions are available exclusively in **Prowler Cloud**:
**Manage Ingestions:** Submit and manage findings ingestion jobs via the API. Required to upload OCSF scan results using the `--push-to-cloud` CLI flag or the ingestion endpoints. See [Import Findings](/user-guide/tutorials/prowler-app-import-findings) for details.
**Manage Ingestions:** Submit and manage findings ingestion jobs via the API. Required to upload OCSF scan results using the `--export-ocsf` CLI flag or the ingestion endpoints. See [Findings Ingestion](/user-guide/tutorials/prowler-app-findings-ingestion) for details.
**Manage Billing:** Access and manage billing settings, subscription plans, and payment methods.

View File

@@ -134,18 +134,6 @@ Track the progress of your scan in the `Scans` section:
<img src="/images/scan-progress.png" alt="Scan Progress" width="700" />
<Note>
**How Dashboards Display Scan Data**
Each dashboard handles scan data differently:
* **Overview** displays aggregated metrics from the **latest completed scan per provider** only.
* **Findings** displays results from the **latest completed scan per provider** by default. To access historical findings, apply a date or scan filter.
* **Resources** lists **all discovered resources across all scans**. However, when selecting a resource, the Findings tab within the resource detail shows only findings from the **latest completed scan**. If the latest scan did not evaluate a particular resource, its Findings tab may appear empty.
When a new scan completes or a new data ingestion is processed, the dashboards automatically reflect the updated results.
</Note>
## **Step 8: Analyze the Findings**
While the scan is running, start exploring the findings in these sections:

View File

@@ -1,545 +0,0 @@
---
title: 'AWS Organizations in Prowler Cloud'
description: 'Onboard all AWS accounts in your Organization through a single guided wizard'
---
import { VersionBadge } from "/snippets/version-badge.mdx"
<VersionBadge version="5.19.0" />
Prowler Cloud enables you to onboard all AWS accounts in your Organization through a single guided wizard. Instead of connecting accounts one by one, you can discover every account in your AWS Organization, select the ones you want to monitor, test connectivity, and launch scans — all from the Prowler Cloud UI.
<Note>
This feature is **exclusively available in Prowler Cloud**. For CLI-based multi-account scanning, see [AWS Organizations in Prowler CLI](/user-guide/providers/aws/organizations).
</Note>
## Overview
### Individual Accounts vs Organizations
| Approach | Best for | How it works |
|----------|----------|--------------|
| **Individual accounts** | A few AWS accounts | Connect each account one by one with its own IAM role. |
| **AWS Organizations** | 10+ accounts, or any org-managed environment | Connect once to your management account, discover all member accounts automatically, and scan them in bulk. |
### How it works
Before using the AWS Organizations wizard, you need to deploy **two IAM roles** in your AWS environment. The onboarding follows this sequence:
<Frame>
<img src="/images/organizations/onboarding-flow.svg" alt="Onboarding flow: 1. Create Management Account Role, 2. Deploy StackSet, 3. Run the Wizard, 4. Launch Scans" />
</Frame>
## Key Concepts
### What is an External ID?
An **External ID** is a security token that Prowler generates unique to your tenant. When Prowler assumes the IAM role in your AWS account, it presents this External ID to prove its identity.
This prevents the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html) — a scenario where an unauthorized party could trick AWS into granting access to your account. By requiring the External ID, only your specific Prowler tenant can assume the role.
You don't need to create the External ID yourself — Prowler generates it automatically and displays it in the wizard for you to copy.
### Two Roles Architecture
Prowler requires **two separate IAM roles** deployed in different places, each with a distinct purpose:
| Role | Where it lives | What it does | How to deploy it |
|------|---------------|--------------|------------------|
| **ProwlerScan** (management account) | Your management (root) account only | Discovers the Organization structure **and** scans the management account. Has additional Organizations discovery permissions. | **Manually** in the IAM Console ([Step 1](#step-1-create-the-management-account-role)). Cannot be deployed via StackSet. |
| **ProwlerScan** (member accounts) | Every member account | Scans the account for security findings. | Via **CloudFormation StackSet** ([Step 2](#step-2-deploy-the-cloudformation-stackset)). Automated across all accounts. |
<Frame caption="Both roles share the same name `ProwlerScan`. The management account role includes additional Organization discovery permissions.">
<img src="/images/organizations/two-roles-architecture.svg" alt="Two Roles Architecture: ProwlerScan in management account (discovery + scanning) and ProwlerScan in member accounts (scanning only)" />
</Frame>
<Note>
**Same name, different permissions.** Both roles are named `ProwlerScan` — Prowler expects a consistent role name across all accounts. The management account role has the same scanning permissions as member accounts, plus additional Organizations discovery permissions (see [Step 1](#step-1-create-the-management-account-role) for the full list).
</Note>
### What is a CloudFormation StackSet?
A [CloudFormation StackSet](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html) lets you deploy the same CloudFormation template across multiple AWS accounts in a single operation. Prowler uses a StackSet to deploy the **ProwlerScan** IAM role into every member account of your organization, so you don't have to create the role manually in each account.
## Prerequisites
### Prowler Cloud Account
You need an active [Prowler Cloud](https://cloud.prowler.com) account. Each AWS account you connect will count as a provider in your subscription. See [Billing Impact](#billing-impact) for details.
### AWS Organization Enabled
Your AWS environment must have [AWS Organizations](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_introduction.html) enabled. You will need access to the **management account** (or a delegated administrator account) to provide the Organization ID and IAM Role ARN.
## Step 1: Create the Management Account Role
The first role you need to create is the **management account role**. This role allows Prowler to discover your Organization structure — listing accounts, OUs, and hierarchy.
<Warning>
**This role must be created manually.** Organizational CloudFormation StackSets do not deploy to the management account itself — this is an AWS limitation, not a Prowler one. StackSets with service-managed permissions only target member accounts. Similarly, the Prowler Quick Create link only deploys the role to member accounts.
</Warning>
<Note>
**The role must be named `ProwlerScan`** — the same name as the role deployed to member accounts via StackSet. Prowler expects a consistent role name across all accounts in the Organization. If you use a different name, connection tests and scans will fail for the management account.
</Note>
### Create the IAM Role
1. Sign in to the [AWS IAM Console](https://console.aws.amazon.com/iam/) in your **management account**.
2. Go to **Roles > Create role** and select **Custom trust policy**.
3. Paste the following trust policy. This allows Prowler Cloud to assume the role using your tenant's External ID (you will get this from the Prowler wizard in [Step 3](#step-3-start-the-organization-wizard)):
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::232136659152:root"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "<YOUR_EXTERNAL_ID>"
},
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::232136659152:role/prowler*"
}
}
}
]
}
```
Replace `<YOUR_EXTERNAL_ID>` with the External ID shown in the Prowler wizard.
4. Attach the following AWS managed policies:
- **SecurityAudit**
- **ViewOnlyAccess**
This allows Prowler to also scan the management account for security findings, just like any other account.
5. Create an additional inline policy with the following permissions. These are specific to the management account and allow Prowler to discover your Organization structure:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ProwlerOrganizationDiscovery",
"Effect": "Allow",
"Action": [
"organizations:DescribeAccount",
"organizations:DescribeOrganization",
"organizations:ListAccounts",
"organizations:ListAccountsForParent",
"organizations:ListOrganizationalUnitsForParent",
"organizations:ListRoots",
"organizations:ListTagsForResource"
],
"Resource": "*"
},
{
"Sid": "ProwlerStackSetManagement",
"Effect": "Allow",
"Action": [
"organizations:RegisterDelegatedAdministrator",
"iam:CreateServiceLinkedRole"
],
"Resource": "*"
}
]
}
```
<Tip>
You can optionally restrict the `Resource` field to your specific Organization ARN (e.g., `arn:aws:organizations::123456789012:organization/o-abc123def4`) instead of `"*"` to minimize the blast radius.
</Tip>
6. Name the role **`ProwlerScan`** and click **Create role**. Take note of the **Role ARN** — you will need it in the Prowler wizard.
The ARN follows this format: `arn:aws:iam::<account-id>:role/ProwlerScan`
<Warning>
The role **must** be named `ProwlerScan`. Do not use a different name.
</Warning>
<Note>
If you just created the role, it may take up to **60 seconds** for AWS to propagate it. If you get an error in the Prowler wizard, wait a moment and try again.
</Note>
## Step 2: Deploy the CloudFormation StackSet
After creating the management account role, the next step is to deploy the **ProwlerScan** role to your member accounts using a CloudFormation StackSet. This is the recommended method for consistent, scalable deployment across your entire organization.
The StackSet uses **service-managed permissions**, which means AWS Organizations handles the cross-account deployment automatically — you don't need to create execution roles manually in each account. The StackSet deploys the ProwlerScan IAM role in every target member account, enabling Prowler to assume that role for cross-account scanning.
<Note>
**Trusted access required:** CloudFormation StackSets must have trusted access enabled in your management account. Verify this in the AWS Console under **AWS Organizations > Settings > Trusted access for AWS CloudFormation StackSets**.
</Note>
### Option A: Using the Prowler Quick Create Link (Recommended)
The Prowler wizard provides a one-click link that opens the AWS Console with everything pre-configured.
<Tip>
**[Open Quick Create in AWS Console →](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/quickcreate?templateURL=https%3A%2F%2Fprowler-cloud-public.s3.eu-west-1.amazonaws.com%2Fpermissions%2Ftemplates%2Faws%2Fcloudformation%2Fprowler-scan-role.yml&stackName=Prowler)**
Opens the CloudFormation Console with the Prowler scan role template and parameters pre-configured. You can also find this link in the Prowler wizard during [Step 4: Authentication](#step-4-authenticate-with-your-management-account).
</Tip>
1. Review the pre-filled parameters:
- **Template URL**: Points to the official [Prowler scan role template](https://prowler-cloud-public.s3.eu-west-1.amazonaws.com/permissions/templates/aws/cloudformation/prowler-scan-role.yml) hosted on Prowler's public S3 bucket.
- **ExternalId**: Pre-filled with your tenant's External ID when clicking the link from the Prowler Cloud wizard. If you open this link directly, you will need to enter the External ID manually.
{/* TODO: screenshot of AWS Console Quick Create page showing pre-filled parameters */}
2. Under **Deployment targets**, select:
- **Deploy to organization** to deploy to all accounts, or
- **Deploy to organizational units (OUs)** and specify the OU IDs you want to cover.
3. Review the settings and click **Create StackSet**. AWS will begin deploying the ProwlerScan role to every target account.
### Option B: Manual StackSet Deployment
If you prefer full control over the deployment:
1. Open the [AWS CloudFormation Console](https://console.aws.amazon.com/cloudformation/) in your management account.
2. Go to **StackSets > Create StackSet**.
3. Choose **Service-managed permissions**.
4. Use this template URL:
```
https://prowler-cloud-public.s3.eu-west-1.amazonaws.com/permissions/templates/aws/cloudformation/prowler-scan-role.yml
```
5. Set the **ExternalId** parameter to the External ID shown in the Prowler wizard.
6. Choose your deployment targets (entire organization or specific OUs).
7. Select the AWS regions where you want the role deployed.
8. Click **Create StackSet**.
### Verify StackSet Deployment
After deploying, verify that all stack instances completed successfully:
1. In the CloudFormation Console, go to **StackSets** and select your Prowler StackSet.
2. Click the **Stack instances** tab.
3. Confirm that all instances show **Status: CURRENT** and **Stack status: CREATE_COMPLETE**.
Deployment typically takes **25 minutes** for medium-sized organizations. Large organizations (500+ accounts) may take longer.
<Note>
**Prefer Terraform?** You can deploy the ProwlerScan role using Terraform instead. See the [StackSets deployment guide](/user-guide/providers/aws/organizations#deploying-prowler-iam-roles-across-aws-organizations) for the Terraform module.
</Note>
### Key Considerations
- **Service-managed permissions**: Always select **Service-managed permissions** when creating the StackSet. This lets AWS Organizations manage the deployment automatically across current and future member accounts.
- **Least privilege**: The ProwlerScan role deployed by the StackSet uses `SecurityAudit` and `ViewOnlyAccess` — AWS managed policies that grant read-only access — plus a small set of additional read-only permissions for services not covered by those policies. See the [CloudFormation template](https://prowler-cloud-public.s3.eu-west-1.amazonaws.com/permissions/templates/aws/cloudformation/prowler-scan-role.yml) for the full list. Prowler does not make any changes to your accounts.
- **New accounts**: When you add new accounts to your AWS Organization, the StackSet automatically deploys the ProwlerScan role to them if you targeted the organization root or the relevant OU. Combined with Prowler's 6-hour automatic sync, new accounts are onboarded end-to-end without manual intervention.
- **Management account**: Organizational StackSets **do not deploy to the management account itself**. If you want to scan the management account, you need to create the ProwlerScan role there separately using a regular CloudFormation Stack.
## Step 3: Start the Organization Wizard
Now that both roles are deployed — the management account role (Step 1) and the ProwlerScan role in member accounts (Step 2) — you can start the Prowler wizard.
### Open the Wizard
1. Navigate to **Cloud Providers** and click **Add Cloud Provider**.
<Frame>
<img src="/images/organizations/cloud-providers-add.png" alt="Cloud Providers page showing the Add Cloud Provider button" />
</Frame>
2. Select **Amazon Web Services** as the provider.
<Frame>
<img src="/images/organizations/select-aws-provider.png" alt="Provider selection modal with Amazon Web Services highlighted" />
</Frame>
3. Choose **Add Multiple Accounts With AWS Organizations**.
<Frame>
<img src="/images/organizations/select-organizations-method.png" alt="Method selector showing Add Multiple Accounts With AWS Organizations option highlighted" />
</Frame>
### Enter Organization Details
- **Organization ID**: Your AWS Organization identifier, found in the [AWS Organizations Console](https://console.aws.amazon.com/organizations/). It follows the format `o-` followed by 1032 lowercase alphanumeric characters (e.g., `o-abc123def4`). You can find it in the left sidebar of the AWS Organizations console:
<Frame>
<img src="/images/organizations/aws-console-org-id.png" alt="AWS Organizations Console showing the Organization ID in the left sidebar" />
</Frame>
- **Name** (optional): A display name for the organization. If left blank, Prowler uses the name stored in AWS.
<Frame>
<img src="/images/organizations/organization-details-form.png" alt="Organization Details form with Organization ID and Name fields" />
</Frame>
Click **Next** to proceed to the authentication phase.
## Step 4: Authenticate with Your Management Account
### Copy the External ID
The wizard displays a **Prowler External ID** — auto-generated and unique to your tenant. Click the copy icon to copy it. If you haven't already configured the trust policy on your management account role ([Step 1](#step-1-create-the-management-account-role)), do so now using this External ID.
<Frame>
<img src="/images/organizations/authentication-details.png" alt="Authentication Details form showing External ID, Role ARN field, and StackSet confirmation checkbox" />
</Frame>
### Enter the Role ARN
Paste the **Role ARN** of the management account role you created in [Step 1](#step-1-create-the-management-account-role) into the **Role ARN** field.
The ARN follows this format:
```
arn:aws:iam::<account-id>:role/<role-name>
```
For example: `arn:aws:iam::123456789012:role/ProwlerScan`
<Frame>
<img src="/images/organizations/role-arn-field.png" alt="Role ARN field in the Authentication Details form" />
</Frame>
### Confirm and Discover
1. Check the box: **"The StackSet has been successfully deployed in AWS"**.
2. Click **Authenticate**.
Here's what happens behind the scenes:
- Prowler creates the organization resource and stores your credentials securely.
- An asynchronous discovery is triggered to query your AWS Organization structure.
- You will see a **"Gathering AWS Accounts..."** spinner — this typically takes **30 seconds to 2 minutes** depending on your organization size.
{/* TODO: screenshot of the Authentication Details form with the spinner */}
## Step 5: Select Accounts to Scan
### Understanding the Tree View
Once discovery completes, the wizard displays a **hierarchical tree view** of your Organization:
<Frame>
<img src="/images/organizations/tree-view-accounts.png" alt="Hierarchical tree view showing OUs and accounts with selection checkboxes" />
</Frame>
- The tree supports up to **5 levels of nesting** (Root > OUs > Sub-OUs > Accounts).
- **Selecting an OU** automatically selects all accounts within it.
- **Individual overrides**: deselect specific accounts even if the parent OU is selected.
- The header shows **"X of Y accounts selected"** to track your selection.
### Account Statuses
Only **ACTIVE** accounts can be selected for scanning:
| Status | Selectable? | Description |
|--------|-------------|-------------|
| **ACTIVE** | Yes | Account is active and operational. |
| **SUSPENDED** | No | Account is suspended by AWS. |
| **PENDING_CLOSURE** | No | Account is being closed. |
| **CLOSED** | No | Account has been closed. |
<Note>
**Your existing data is safe.** If an AWS account is already connected to Prowler as an individual provider, it will appear in the tree with a checkmark indicator.
When you proceed:
- The existing provider is **linked** to the organization — it is **not** duplicated.
- All your **historical scan data and findings are preserved** — nothing is overwritten.
- There is **no additional billing** — the existing provider is reused.
This is completely safe. You are simply associating the account with the organization for easier management.
</Note>
### Custom Aliases
You can edit the display name for each account before connecting. This alias is only used in Prowler — it does not affect your AWS account name.
### Blocked Accounts
Some accounts may appear as **blocked** (grayed out, not selectable). This happens when:
- The account is **already linked to a different organization** in Prowler (`linked_to_other_organization`).
Hover over the blocked account to see the specific reason.
{/* TODO: screenshot of the tree view with account selection, showing active, already-connected, and blocked accounts */}
## Step 6: Test Connections
### How Connection Testing Works
Click **Test Connections** to verify that Prowler can assume the **ProwlerScan** role in each selected member account.
<Frame>
<img src="/images/organizations/test-connections.png" alt="Connection testing in progress with spinners on each account" />
</Frame>
- Each account shows a real-time status indicator:
- **Spinner** — test in progress
- **Green checkmark (✓)** — connection successful
- **Red icon (✗)** — connection failed (hover to see the error)
### All Tests Pass
If every account connects successfully, you automatically advance to the next step.
### Some Tests Fail
An error banner appears: **"There was a problem connecting to some accounts."**
You have two options:
**a) Fix and retry:**
1. Go to the AWS Console and verify the StackSet deployed to the failing accounts.
2. Check that the External ID in the StackSet matches the one shown in Prowler.
3. Return to Prowler and click **Test Connections** — only the **failed accounts are re-tested** (smart retry). Accounts that already passed are not tested again.
<Frame>
<img src="/images/organizations/test-connections-button.png" alt="Test Connections button" />
</Frame>
**b) Skip and continue:**
Click **Skip Connection Validation** to proceed with only the accounts that connected successfully. The failed accounts will not be scanned.
<Frame>
<img src="/images/organizations/connection-failures-skip.png" alt="Connection test results showing failed accounts with error banner and Skip Connection Validation button" />
</Frame>
<Note>
**Skip Connection Validation** is only available when at least one account connected successfully.
</Note>
### All Tests Fail
If **no accounts** connected successfully, you cannot proceed:
> *"No accounts connected successfully. Fix the connection errors and retry before launching scans."*
You must fix the underlying connection issues before continuing. See [Updating Credentials](#updating-credentials) below.
### Updating Credentials
If connection tests fail, here's how to fix common issues:
1. Open the [CloudFormation Console](https://console.aws.amazon.com/cloudformation/) and check that your StackSet instances show **CREATE_COMPLETE** for the failing accounts. If not, update the StackSet to include the missing OUs.
2. Compare the **ExternalId** parameter in your StackSet with the External ID displayed in the Prowler wizard. They must match exactly.
3. After fixing the issue in AWS, return to Prowler and click **Test Connections**. Only the previously failed accounts will be re-tested.
## Step 7: Launch Scans
### Choose Scan Schedule
| Schedule Option | Description |
|-----------------|-------------|
| **Scan Daily (every 24 hours)** | Creates a recurring daily scan for all connected accounts (default). |
| **Run a single scan (no recurring schedule)** | Launches a one-time scan. |
### Launch
Click **Launch scan**. A toast notification confirms: *"Scan Launched — Daily scan scheduled for X accounts"* with a link to the Scans page. You will be redirected to the **Providers** page.
Scans are only launched for accounts that are accessible (passed connection testing) and were selected.
<Frame>
<img src="/images/organizations/launch-scan.png" alt="Launch Scan step showing Accounts Connected confirmation, scan schedule selector, and Launch scan button" />
</Frame>
### What Happens Next
- Scans appear in the **Scans** page as they start and complete.
- Results populate the **Overview** and **Findings** pages.
- Prowler runs an **automatic sync every 6 hours** to detect new accounts added to your Organization or accounts that have been removed. New accounts are onboarded automatically based on the parent OU configuration.
{/* TODO: screenshot of the Launch Scan step */}
## Billing Impact
Each AWS account you connect through the Organizations wizard counts as one **provider** in your Prowler Cloud subscription.
- **Already-connected accounts**: if an account was already linked as a provider, adding it to the organization does **not** incur additional billing. The existing provider is reused.
- **Large organizations**: connecting a 500-account organization will result in up to 500 providers on your subscription. Review your plan limits before proceeding.
- **Deleted providers**: if you later remove an account, the deleted provider no longer counts toward your subscription.
For pricing details, see [Prowler Cloud Pricing](/getting-started/products/prowler-cloud-pricing).
## Troubleshooting
### Invalid AWS Organization ID
*"Must be a valid AWS Organization ID"*
- Verify the Organization ID format: `o-` followed by 1032 lowercase alphanumeric characters (e.g., `o-abc123def4`)
- Copy it directly from the [AWS Organizations Console](https://console.aws.amazon.com/organizations/) to avoid typos
### Invalid IAM Role ARN
*"Must be a valid IAM Role ARN"*
- Verify the ARN format: `arn:aws:iam::<12-digit-account-id>:role/<role-name>`
- Copy the ARN directly from the [IAM Console](https://console.aws.amazon.com/iam/) in your management account
### Authentication Failed
*"Authentication failed. Please verify the StackSet deployment and Role ARN"*
- Verify the management account role exists and was created in [Step 1](#step-1-create-the-management-account-role)
- Confirm the trust policy includes the correct External ID from the wizard
- Check the role has all Organizations discovery permissions listed in [Step 1](#step-1-create-the-management-account-role)
- Double-check the Role ARN format and account ID for typos
### Authentication Timed Out
*"Authentication timed out"*
- Retry the authentication step — the second attempt often succeeds
- Check for AWS API rate limiting on the Organizations service
- For very large organizations (500+ accounts), allow extra time for discovery
### Connection Test Fails for All Accounts
No accounts pass the connection test.
- Verify the CloudFormation StackSet was deployed — complete [Step 2](#step-2-deploy-the-cloudformation-stackset) and wait for stack instances to reach **CREATE_COMPLETE**
- Check that the **ExternalId** parameter in the StackSet matches the External ID shown in the Prowler wizard
- If your accounts use IP-based IAM policies, allow [Prowler Cloud public IPs](/user-guide/tutorials/prowler-cloud-public-ips)
### Connection Test Fails for Some Accounts
Some accounts show a red icon while others pass.
- Expand the StackSet deployment to include the OUs containing the failing accounts
- Suspended accounts cannot be scanned — deselect them and proceed
- Ensure the [STS regional endpoint](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_enable-regions.html) is enabled in the account's region
- After fixing, click **Test Connections** — only the failed accounts will be re-tested
### No Accounts Connected Successfully
*"No accounts connected successfully. Fix the connection errors and retry before launching scans."*
- Hover over the red icon on each account to see the specific error
- Fix the underlying issues using the guidance above
- Click **Test Connections** to retry
### Failed to Apply Discovery
*"Failed to apply discovery"*
- Check the `blocked_reasons` field for any blocked accounts
- Retry the operation
- If the error persists, contact [Prowler Support](mailto:support@prowler.com)
## What's Next
<Columns cols={2}>
<Card title="Prowler Cloud" icon="cloud" href="/user-guide/tutorials/prowler-app">
Full guide to using Prowler Cloud features.
</Card>
<Card title="AWS Organizations (CLI)" icon="terminal" href="/user-guide/providers/aws/organizations">
CLI-based Organizations scanning and StackSet deployment with Terraform.
</Card>
<Card title="Bulk Provider Provisioning" icon="upload" href="/user-guide/tutorials/bulk-provider-provisioning">
Script-based bulk provisioning for advanced automation.
</Card>
</Columns>

View File

@@ -2,58 +2,52 @@
All notable changes to the **Prowler MCP Server** are documented in this file.
## [0.4.0] (Prowler v5.19.0)
## [0.4.0] (Prowler UNRELEASED)
### 🚀 Added
- Attack Paths tools to list scans, discover queries, and run Cypher queries against Neo4j [(#10145)](https://github.com/prowler-cloud/prowler/pull/10145)
---
- Add new MCP Server tools for Prowler Attack Paths [(#10145)](https://github.com/prowler-cloud/prowler/pull/10145)
## [0.3.0] (Prowler v5.16.0)
### 🚀 Added
### Added
- MCP Server tools for Prowler Compliance Framework Management [(#9568)](https://github.com/prowler-cloud/prowler/pull/9568)
- Add new MCP Server tools for Prowler Compliance Framework Management [(#9568)](https://github.com/prowler-cloud/prowler/pull/9568)
### 🔄 Changed
### Changed
- API base URL environment variable to include complete path [(#9542)](https://github.com/prowler-cloud/prowler/pull/9542)
- Prowler Hub and Docs tools format standardized for AI optimization [(#9578)](https://github.com/prowler-cloud/prowler/pull/9578)
---
- Update API base URL environment variable to include complete path [(#9542)](https://github.com/prowler-cloud/prowler/pull/9542)
- Standardize Prowler Hub and Docs tools format for AI optimization [(#9578)](https://github.com/prowler-cloud/prowler/pull/9578)
## [0.2.0] (Prowler v5.15.0)
### 🚀 Added
### Added
- MCP Server tools for Prowler Findings and Compliance, replacing all Prowler App MCP tools [(#9300)](https://github.com/prowler-cloud/prowler/pull/9300)
- MCP Server tools for Prowler Providers Management [(#9350)](https://github.com/prowler-cloud/prowler/pull/9350)
- MCP Server tools for Prowler Resources Management [(#9380)](https://github.com/prowler-cloud/prowler/pull/9380)
- MCP Server tools for Prowler Scans Management [(#9509)](https://github.com/prowler-cloud/prowler/pull/9509)
- MCP Server tools for Prowler Muting Management [(#9510)](https://github.com/prowler-cloud/prowler/pull/9510)
- Remove all Prowler App MCP tools; and add new MCP Server tools for Prowler Findings and Compliance [(#9300)](https://github.com/prowler-cloud/prowler/pull/9300)
- Add new MCP Server tools for Prowler Providers Management [(#9350)](https://github.com/prowler-cloud/prowler/pull/9350)
- Add new MCP Server tools for Prowler Resources Management [(#9380)](https://github.com/prowler-cloud/prowler/pull/9380)
- Add new MCP Server tools for Prowler Scans Management [(#9509)](https://github.com/prowler-cloud/prowler/pull/9509)
- Add new MCP Server tools for Prowler Muting Management [(#9510)](https://github.com/prowler-cloud/prowler/pull/9510)
---
## [0.1.1] (Prowler v5.14.0)
### 🐞 Fixed
### Fixed
- Documentation MCP Server to return list of dictionaries [(#9205)](https://github.com/prowler-cloud/prowler/pull/9205)
- Fix documentation MCP Server to return list of dictionaries [(#9205)](https://github.com/prowler-cloud/prowler/pull/9205)
---
## [0.1.0] (Prowler v5.13.0)
### 🚀 Added
### Added
- Initial release of Prowler MCP Server [(#8695)](https://github.com/prowler-cloud/prowler/pull/8695)
- Appropriate user-agent in requests [(#8724)](https://github.com/prowler-cloud/prowler/pull/8724)
- Set appropiate user-agent in requests [(#8724)](https://github.com/prowler-cloud/prowler/pull/8724)
- Basic logger functionality [(#8740)](https://github.com/prowler-cloud/prowler/pull/8740)
- MCP Server for Prowler Cloud and Prowler App (Self-Managed) APIs [(#8744)](https://github.com/prowler-cloud/prowler/pull/8744)
- Add new MCP Server for Prowler Cloud and Prowler App (Self-Managed) APIs [(#8744)](https://github.com/prowler-cloud/prowler/pull/8744)
- HTTP transport support [(#8784)](https://github.com/prowler-cloud/prowler/pull/8784)
- MCP Server for Prowler Documentation [(#8795)](https://github.com/prowler-cloud/prowler/pull/8795)
- Add new MCP Server for Prowler Documentation [(#8795)](https://github.com/prowler-cloud/prowler/pull/8795)
- API key support for STDIO mode and enhanced HTTP mode authentication [(#8823)](https://github.com/prowler-cloud/prowler/pull/8823)
- Health check endpoint [(#8905)](https://github.com/prowler-cloud/prowler/pull/8905)
- Prowler Documentation MCP Server updated to use Mintlify API [(#8916)](https://github.com/prowler-cloud/prowler/pull/8916)
- Custom production deployment using uvicorn [(#8958)](https://github.com/prowler-cloud/prowler/pull/8958)
- Add health check endpoint [(#8905)](https://github.com/prowler-cloud/prowler/pull/8905)
- Update Prowler Documentation MCP Server to use Mintlify API [(#8916)](https://github.com/prowler-cloud/prowler/pull/8916)
- Add custom production deployment using uvicorn [(#8958)](https://github.com/prowler-cloud/prowler/pull/8958)

View File

@@ -36,15 +36,6 @@ Parameters:
The IAM principal type and name that will be allowed to assume the role created, leave an * for all the IAM principals in your AWS account. If you are deploying this template to be used in Prowler Cloud please do not edit this.
Type: String
Default: role/prowler*
EnableOrganizations:
Description: |
Enable AWS Organizations discovery permissions. Set to true only when deploying this role in the management account.
This adds read-only Organizations permissions (e.g. ListAccounts, DescribeOrganization) and StackSet management permissions.
Type: String
Default: false
AllowedValues:
- true
- false
EnableS3Integration:
Description: |
Enable S3 integration for storing Prowler scan reports.
@@ -65,7 +56,6 @@ Parameters:
Default: ""
Conditions:
OrganizationsEnabled: !Equals [!Ref EnableOrganizations, true]
S3IntegrationEnabled: !Equals [!Ref EnableS3Integration, true]
@@ -150,30 +140,6 @@ Resources:
Resource:
- "arn:*:apigateway:*::/restapis/*"
- "arn:*:apigateway:*::/apis/*"
- !If
- OrganizationsEnabled
- PolicyName: ProwlerOrganizations
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowOrganizationsReadOnly
Effect: Allow
Action:
- "organizations:DescribeAccount"
- "organizations:DescribeOrganization"
- "organizations:ListAccounts"
- "organizations:ListAccountsForParent"
- "organizations:ListOrganizationalUnitsForParent"
- "organizations:ListRoots"
- "organizations:ListTagsForResource"
Resource: "*"
- Sid: AllowStackSetManagement
Effect: Allow
Action:
- "organizations:RegisterDelegatedAdministrator"
- "iam:CreateServiceLinkedRole"
Resource: "*"
- !Ref AWS::NoValue
- !If
- S3IntegrationEnabled
- PolicyName: S3Integration
@@ -225,7 +191,6 @@ Metadata:
- ExternalId
- AccountId
- IAMPrincipal
- EnableOrganizations
- EnableS3Integration
- Label:
default: Optional

View File

@@ -67,45 +67,6 @@ resource "aws_iam_role_policy_attachment" "prowler_scan_viewonly_policy_attachme
policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/job-function/ViewOnlyAccess"
}
# Organizations Policy (management account only)
###################################
data "aws_iam_policy_document" "prowler_organizations_policy" {
count = var.enable_organizations ? 1 : 0
statement {
sid = "AllowOrganizationsReadOnly"
effect = "Allow"
actions = [
"organizations:DescribeAccount",
"organizations:DescribeOrganization",
"organizations:ListAccounts",
"organizations:ListAccountsForParent",
"organizations:ListOrganizationalUnitsForParent",
"organizations:ListRoots",
"organizations:ListTagsForResource",
]
resources = ["*"]
}
statement {
sid = "AllowStackSetManagement"
effect = "Allow"
actions = [
"organizations:RegisterDelegatedAdministrator",
"iam:CreateServiceLinkedRole",
]
resources = ["*"]
}
}
resource "aws_iam_role_policy" "prowler_organizations_policy" {
count = var.enable_organizations ? 1 : 0
name = "ProwlerOrganizations"
role = aws_iam_role.prowler_scan.name
policy = data.aws_iam_policy_document.prowler_organizations_policy[0].json
}
# S3 Integration Module
###################################
module "s3_integration" {

View File

@@ -27,12 +27,6 @@ variable "iam_principal" {
default = "role/prowler*"
}
variable "enable_organizations" {
type = bool
description = "Enable AWS Organizations discovery permissions. Set to true only when deploying this role in the management account."
default = false
}
variable "enable_s3_integration" {
type = bool
description = "Enable S3 integration for storing Prowler scan reports."

View File

@@ -2,47 +2,40 @@
All notable changes to the **Prowler SDK** are documented in this file.
## [5.19.0] (Prowler v5.19.0)
## [5.19.0] (Prowler UNRELEASED)
### 🚀 Added
- `entra_authentication_method_sms_voice_disabled` check for M365 provider [(#10212)](https://github.com/prowler-cloud/prowler/pull/10212)
- `entra_default_app_management_policy_enabled` check for M365 provider [(#9898)](https://github.com/prowler-cloud/prowler/pull/9898)
- `Google Workspace` provider support with Directory service including 1 security check [(#10022)](https://github.com/prowler-cloud/prowler/pull/10022)
- `entra_conditional_access_policy_app_enforced_restrictions` check for M365 provider [(#10058)](https://github.com/prowler-cloud/prowler/pull/10058)
- `entra_app_registration_no_unused_privileged_permissions` check for M365 provider [(#10080)](https://github.com/prowler-cloud/prowler/pull/10080)
- `entra_app_enforced_restrictions` check for M365 provider [(#10058)](https://github.com/prowler-cloud/prowler/pull/10058)
- `entra_app_registration_no_unused_privileged_permissions` check for m365 provider [(#10080)](https://github.com/prowler-cloud/prowler/pull/10080)
- `defenderidentity_health_issues_no_open` check for M365 provider [(#10087)](https://github.com/prowler-cloud/prowler/pull/10087)
- `organization_verified_badge` check for GitHub provider [(#10033)](https://github.com/prowler-cloud/prowler/pull/10033)
- OpenStack provider `clouds_yaml_content` parameter for API integration [(#10003)](https://github.com/prowler-cloud/prowler/pull/10003)
- `defender_safe_attachments_policy_enabled` check for M365 provider [(#9833)](https://github.com/prowler-cloud/prowler/pull/9833)
- `defender_safelinks_policy_enabled` check for M365 provider [(#9832)](https://github.com/prowler-cloud/prowler/pull/9832)
- AI Skills: Added a skill for creating new Attack Paths queries in openCypher, compatible with Neo4j and Neptune [(#9975)](https://github.com/prowler-cloud/prowler/pull/9975)
- CSA CCM 4.0 for the AWS provider [(#10018)](https://github.com/prowler-cloud/prowler/pull/10018)
- CSA CCM 4.0 for the GCP provider [(#10042)](https://github.com/prowler-cloud/prowler/pull/10042)
- CSA CCM 4.0 for the Azure provider [(#10039)](https://github.com/prowler-cloud/prowler/pull/10039)
- CSA CCM 4.0 for the Oracle Cloud provider [(#10057)](https://github.com/prowler-cloud/prowler/pull/10057)
- OCI regions updater script and CI workflow [(#10020)](https://github.com/prowler-cloud/prowler/pull/10020)
- `image` provider for container image scanning with Trivy integration [(#9984)](https://github.com/prowler-cloud/prowler/pull/9984)
- OpenStack compute 7 new checks [(#9944)](https://github.com/prowler-cloud/prowler/pull/9944)
- CSA CCM 4.0 for the Alibaba Cloud provider [(#10061)](https://github.com/prowler-cloud/prowler/pull/10061)
- ECS Exec (ECS-006) privilege escalation detection via `ecs:ExecuteCommand` + `ecs:DescribeTasks` [(#10066)](https://github.com/prowler-cloud/prowler/pull/10066)
- `--export-ocsf` CLI flag to upload OCSF scan results to Prowler Cloud [(#10095)](https://github.com/prowler-cloud/prowler/pull/10095)
- `scan_id` field in OCSF `unmapped` output for ingestion correlation [(#10095)](https://github.com/prowler-cloud/prowler/pull/10095)
- `defenderxdr_endpoint_privileged_user_exposed_credentials` check for M365 provider [(#10084)](https://github.com/prowler-cloud/prowler/pull/10084)
- `defenderxdr_critical_asset_management_pending_approvals` check for M365 provider [(#10085)](https://github.com/prowler-cloud/prowler/pull/10085)
- `entra_seamless_sso_disabled` check for M365 provider [(#10086)](https://github.com/prowler-cloud/prowler/pull/10086)
- `entra_seamless_sso_disabled` check for m365 provider [(#10086)](https://github.com/prowler-cloud/prowler/pull/10086)
- Registry scan mode for `image` provider: enumerate and scan all images from OCI standard, Docker Hub, and ECR [(#9985)](https://github.com/prowler-cloud/prowler/pull/9985)
- File descriptor limits (`ulimits`) for Docker Compose worker services to prevent `Too many open files` errors [(#10107)](https://github.com/prowler-cloud/prowler/pull/10107)
- Add file descriptor limits (`ulimits`) to Docker Compose worker services to prevent `Too many open files` errors [(#10107)](https://github.com/prowler-cloud/prowler/pull/10107)
- SecNumCloud compliance framework for the AWS provider [(#10117)](https://github.com/prowler-cloud/prowler/pull/10117)
- CIS 6.0 for the AWS provider [(#10127)](https://github.com/prowler-cloud/prowler/pull/10127)
- `entra_conditional_access_policy_require_mfa_for_management_api` check for M365 provider [(#10150)](https://github.com/prowler-cloud/prowler/pull/10150)
- `entra_require_mfa_for_management_api` check for m365 provider [(#10150)](https://github.com/prowler-cloud/prowler/pull/10150)
- OpenStack provider multiple regions support [(#10135)](https://github.com/prowler-cloud/prowler/pull/10135)
- `entra_break_glass_account_fido2_security_key_registered` check for M365 provider [(#10213)](https://github.com/prowler-cloud/prowler/pull/10213)
- `entra_default_app_management_policy_enabled` check for M365 provider [(#9898)](https://github.com/prowler-cloud/prowler/pull/9898)
- OpenStack networking service with 6 security checks [(#9970)](https://github.com/prowler-cloud/prowler/pull/9970)
- OpenStack block storage service with 7 security checks [(#10120)](https://github.com/prowler-cloud/prowler/pull/10120)
- OpenStack compute service with 7 security checks [(#9944)](https://github.com/prowler-cloud/prowler/pull/9944)
- OpenStack image service with 6 security checks [(#10096)](https://github.com/prowler-cloud/prowler/pull/10096)
- `--provider-uid` CLI flag for IaC provider, used as `cloud.account.uid` in OCSF output and required with `--export-ocsf` [(#10233)](https://github.com/prowler-cloud/prowler/pull/10233)
- `unmapped.provider_uid` field in OCSF output to match CLI scan results with API provider entities during ingestion [(#10231)](https://github.com/prowler-cloud/prowler/pull/10231)
- `unmapped.provider` field in OCSF output for provider name availability in non-cloud providers like Kubernetes [(#10240)](https://github.com/prowler-cloud/prowler/pull/10240)
### 🔄 Changed
@@ -65,25 +58,24 @@ All notable changes to the **Prowler SDK** are documented in this file.
- Update Azure Entra ID service metadata to new format [(#9619)](https://github.com/prowler-cloud/prowler/pull/9619)
- Update Azure Virtual Machines service metadata to new format [(#9629)](https://github.com/prowler-cloud/prowler/pull/9629)
- Cloudflare provider credential validation with specific exceptions [(#9910)](https://github.com/prowler-cloud/prowler/pull/9910)
- Enhance AWS IAM privilege escalation detection with patterns from pathfinding.cloud library [(#9922)](https://github.com/prowler-cloud/prowler/pull/9922)
- Bump Trivy from 0.66.0 to 0.69.2 [(#10210)](https://github.com/prowler-cloud/prowler/pull/10210)
- Standardize GitHub and M365 provider account UIDs for consistent OCSF output [(#10226)](https://github.com/prowler-cloud/prowler/pull/10226)
- Standardize Cloudflare account and resource UIDs to prevent None values in findings [(#10227)](https://github.com/prowler-cloud/prowler/pull/10227)
### 🐞 Fixed
- Update AWS checks metadata URLs to replace deprecated Trend Micro CloudOne Conformity (EOL July 2026) with Vision One and remove docs.prowler.com references [(#10068)](https://github.com/prowler-cloud/prowler/pull/10068)
- Standardize resource_id values across Azure checks to use actual Azure resource IDs and prevent duplicate resource entries [(#9994)](https://github.com/prowler-cloud/prowler/pull/9994)
- VPC endpoint service collection filtering third-party services that caused AccessDenied errors on `DescribeVpcEndpointServicePermissions` [(#10152)](https://github.com/prowler-cloud/prowler/pull/10152)
- Handle serialization errors in OCSF output for non-serializable resource metadata [(#10129)](https://github.com/prowler-cloud/prowler/pull/10129)
- Respect `AWS_ENDPOINT_URL` environment variable for STS session creation [(#10228)](https://github.com/prowler-cloud/prowler/pull/10228)
- Help text and typos in CLI flags [(#10040)](https://github.com/prowler-cloud/prowler/pull/10040)
- `elbv2_insecure_ssl_ciphers` false positive on AWS post-quantum (PQ) TLS policies like `ELBSecurityPolicy-TLS13-1-2-PQ-2025-09` [(#10219)](https://github.com/prowler-cloud/prowler/pull/10219)
### 🔐 Security
- Bumped `py-ocsf-models` to 0.8.1 and `cryptography` to 44.0.3 [(#10059)](https://github.com/prowler-cloud/prowler/pull/10059)
- Harden GitHub Actions workflows against expression injection, add `persist-credentials: false` to checkout steps, and configure dependabot cooldown [(#10200)](https://github.com/prowler-cloud/prowler/pull/10200)
---
## [5.18.4] (Prowler v5.18.4)
### 🐞 Fixed
- Handle serialization errors in OCSF output for non-serializable resource metadata [(#10129)](https://github.com/prowler-cloud/prowler/pull/10129)
---
@@ -216,6 +208,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
- Update Azure AI Search service metadata to new format [(#9087)](https://github.com/prowler-cloud/prowler/pull/9087)
- Update Azure AKS service metadata to new format [(#9611)](https://github.com/prowler-cloud/prowler/pull/9611)
- Update Azure API Management service metadata to new format [(#9612)](https://github.com/prowler-cloud/prowler/pull/9612)
- Enhance AWS IAM privilege escalation detection with patterns from pathfinding.cloud library [(#9922)](https://github.com/prowler-cloud/prowler/pull/9922)
### Fixed

View File

@@ -529,7 +529,7 @@ def prowler():
provider=global_provider, stats=stats
)
if getattr(args, "push_to_cloud", False):
if getattr(args, "export_ocsf", False):
if not ocsf_output or not getattr(ocsf_output, "file_path", None):
tmp_ocsf = tempfile.NamedTemporaryFile(
suffix=json_ocsf_file_suffix, delete=False
@@ -541,50 +541,42 @@ def prowler():
tmp_ocsf.close()
ocsf_output.batch_write_data_to_file()
print(
f"{Style.BRIGHT}\nPushing findings to Prowler Cloud, please wait...{Style.RESET_ALL}"
f"{Style.BRIGHT}\nExporting OCSF to Prowler Cloud, please wait...{Style.RESET_ALL}"
)
try:
response = send_ocsf_to_api(ocsf_output.file_path)
except ValueError:
print(
f"{Style.BRIGHT}{Fore.YELLOW}\nPush to Prowler Cloud skipped: no API key configured. "
"Set the PROWLER_CLOUD_API_KEY environment variable to enable it. "
f"Scan results were saved to {ocsf_output.file_path}{Style.RESET_ALL}"
logger.warning(
"OCSF export skipped: no API key configured. "
"Set the PROWLER_API_KEY environment variable to enable it. "
f"Scan results were saved to {ocsf_output.file_path}"
)
except requests.ConnectionError:
print(
f"{Style.BRIGHT}{Fore.RED}\nPush to Prowler Cloud failed: could not reach the Prowler Cloud API at "
logger.warning(
"OCSF export skipped: could not reach the Prowler Cloud API at "
f"{cloud_api_base_url}. Check the URL and your network connection. "
f"Scan results were saved to {ocsf_output.file_path}{Style.RESET_ALL}"
f"Scan results were saved to {ocsf_output.file_path}"
)
except requests.HTTPError as http_err:
if http_err.response.status_code == 402:
print(
f"{Style.BRIGHT}{Fore.RED}\nPush to Prowler Cloud failed: "
"this feature is only available with a Prowler Cloud subscription. "
f"Scan results were saved to {ocsf_output.file_path}{Style.RESET_ALL}"
)
else:
print(
f"{Style.BRIGHT}{Fore.RED}\nPush to Prowler Cloud failed: the API returned HTTP {http_err.response.status_code}. "
"Verify your API key is valid and has the right permissions. "
f"Scan results were saved to {ocsf_output.file_path}{Style.RESET_ALL}"
)
logger.warning(
f"OCSF export failed: the API returned HTTP {http_err.response.status_code}. "
"Verify your API key is valid and has the right permissions. "
f"Scan results were saved to {ocsf_output.file_path}"
)
except Exception as error:
print(
f"{Style.BRIGHT}{Fore.RED}\nPush to Prowler Cloud failed unexpectedly: {error}. "
f"Scan results were saved to {ocsf_output.file_path}{Style.RESET_ALL}"
logger.warning(
f"OCSF export failed unexpectedly: {error}. "
f"Scan results were saved to {ocsf_output.file_path}"
)
else:
job_id = response.get("data", {}).get("id") if response else None
if job_id:
print(
f"{Style.BRIGHT}{Fore.GREEN}\nFindings successfully pushed to Prowler Cloud. Ingestion job: {job_id}"
f"\nSee more details here: https://cloud.prowler.com/scans{Style.RESET_ALL}"
f"{Style.BRIGHT}{Fore.GREEN}\nOCSF export accepted. Ingestion job: {job_id}{Style.RESET_ALL}"
)
else:
logger.warning(
"Push to Prowler Cloud: unexpected API response (missing ingestion job ID). "
"OCSF export: unexpected API response (missing ingestion job ID). "
f"Scan results were saved to {ocsf_output.file_path}"
)

View File

@@ -74,7 +74,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_invite_only_for_admin_roles",
"iam_custom_role_has_permissions_to_administer_resource_locks",
"iam_role_user_access_admin_restricted",
@@ -94,7 +94,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_default_users_cannot_create_security_groups",
"iam_custom_role_has_permissions_to_administer_resource_locks",
"iam_role_user_access_admin_restricted",
@@ -286,7 +286,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_default_users_cannot_create_security_groups",
"entra_policy_guest_invite_only_for_admin_roles",
"entra_policy_user_consent_for_verified_apps",
@@ -709,7 +709,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
"iam_custom_role_has_permissions_to_administer_resource_locks",
@@ -2122,7 +2122,7 @@
"monitor_alert_delete_public_ip_address_rule",
"aks_clusters_public_access_disabled",
"app_function_access_keys_configured",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
"iam_role_user_access_admin_restricted",
@@ -3497,7 +3497,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_user_with_vm_access_has_mfa",
"iam_custom_role_has_permissions_to_administer_resource_locks",
"iam_role_user_access_admin_restricted",
@@ -4522,7 +4522,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_invite_only_for_admin_roles",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
@@ -4894,7 +4894,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
"iam_custom_role_has_permissions_to_administer_resource_locks",
@@ -4917,7 +4917,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
"iam_custom_role_has_permissions_to_administer_resource_locks",
@@ -5053,7 +5053,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_privileged_user_has_mfa",
"entra_user_with_vm_access_has_mfa"
]
@@ -5298,7 +5298,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_privileged_user_has_mfa",
"entra_user_with_vm_access_has_mfa",
"iam_role_user_access_admin_restricted",
@@ -5346,7 +5346,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_policy_user_consent_for_verified_apps",
"entra_user_with_vm_access_has_mfa",
@@ -5429,7 +5429,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_user_with_vm_access_has_mfa"
]
},
@@ -5518,7 +5518,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_non_privileged_user_has_mfa",
"entra_user_with_vm_access_has_mfa"
]
@@ -5557,7 +5557,7 @@
"app_function_not_publicly_accessible",
"containerregistry_not_publicly_accessible",
"containerregistry_uses_private_link",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
"iam_role_user_access_admin_restricted",
@@ -5598,7 +5598,7 @@
"app_function_not_publicly_accessible",
"containerregistry_not_publicly_accessible",
"containerregistry_uses_private_link",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_users_access_restrictions",
"entra_user_with_vm_access_has_mfa",
"iam_role_user_access_admin_restricted",
@@ -9010,7 +9010,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_user_with_vm_access_has_mfa"
@@ -9029,7 +9029,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_privileged_user_has_mfa"
]
},
@@ -9240,7 +9240,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_policy_guest_invite_only_for_admin_roles",
"entra_policy_guest_users_access_restrictions",
"iam_custom_role_has_permissions_to_administer_resource_locks",

View File

@@ -1414,7 +1414,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_global_admin_in_less_than_five_users",
"entra_privileged_user_has_mfa",
"iam_role_user_access_admin_restricted",
@@ -5135,7 +5135,7 @@
"Checks": [
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_security_defaults_enabled",
"entra_user_with_vm_access_has_mfa"
]
@@ -5201,7 +5201,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_security_defaults_enabled"
@@ -5266,7 +5266,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_security_defaults_enabled"
@@ -5331,7 +5331,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_user_with_vm_access_has_mfa"
@@ -5411,7 +5411,7 @@
"keyvault_rbac_enabled",
"keyvault_private_endpoints",
"keyvault_access_only_through_private_endpoints",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_global_admin_in_less_than_five_users",
"entra_non_privileged_user_has_mfa",
"entra_security_defaults_enabled",
@@ -5506,7 +5506,7 @@
"aks_clusters_public_access_disabled",
"app_function_not_publicly_accessible",
"entra_global_admin_in_less_than_five_users",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_trusted_named_locations_exists",
@@ -5571,7 +5571,7 @@
}
],
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_global_admin_in_less_than_five_users",
"entra_non_privileged_user_has_mfa",
"iam_role_user_access_admin_restricted",
@@ -5681,7 +5681,7 @@
"network_ssh_internet_access_restricted",
"network_udp_internet_access_restricted",
"vm_jit_access_enabled",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"entra_global_admin_in_less_than_five_users",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
@@ -5845,7 +5845,7 @@
"entra_global_admin_in_less_than_five_users",
"entra_non_privileged_user_has_mfa",
"entra_privileged_user_has_mfa",
"entra_conditional_access_policy_require_mfa_for_management_api",
"entra_require_mfa_for_management_api",
"keyvault_rbac_enabled",
"vm_jit_access_enabled",
"vm_linux_enforce_ssh_authentication"

View File

@@ -688,7 +688,7 @@
"Id": "1.2.6",
"Description": "Ensure Multifactor Authentication is Required for Windows Azure Service Management API",
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api"
"entra_require_mfa_for_management_api"
],
"Attributes": [
{

View File

@@ -729,7 +729,7 @@
"Id": "2.2.7",
"Description": "Ensure Multi-factor Authentication is Required for Windows Azure Service Management API",
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api"
"entra_require_mfa_for_management_api"
],
"Attributes": [
{

View File

@@ -1013,7 +1013,7 @@
"Id": "6.2.6",
"Description": "Ensure that multifactor authentication is required for Windows Azure Service Management API",
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api"
"entra_require_mfa_for_management_api"
],
"Attributes": [
{

View File

@@ -449,7 +449,7 @@
"Id": "5.2.6",
"Description": "Ensure that multifactor authentication is required for Windows Azure Service Management API",
"Checks": [
"entra_conditional_access_policy_require_mfa_for_management_api"
"entra_require_mfa_for_management_api"
],
"Attributes": [
{

Some files were not shown because too many files have changed in this diff Show More