diff --git a/.env b/.env index 6787267f6f..f83f8ea702 100644 --- a/.env +++ b/.env @@ -14,7 +14,11 @@ UI_PORT=3000 AUTH_SECRET="N/c6mnaS5+SWq81+819OrzQZlmx1Vxtp/orjttJSmw8=" # Google Tag Manager ID NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID="" - +#### Code Review Configuration #### +# Enable Claude Code standards validation on pre-push hook +# Set to 'true' to validate changes against AGENTS.md standards via Claude Code +# Set to 'false' to skip validation +CODE_REVIEW_ENABLED=true #### Prowler API Configuration #### PROWLER_API_VERSION="stable" @@ -132,4 +136,5 @@ LANGCHAIN_PROJECT="" # Example with one source: RSS_FEED_SOURCES='[{"id":"prowler-releases","name":"Prowler Releases","type":"github_releases","url":"https://github.com/prowler-cloud/prowler/releases.atom","enabled":true}]' # Example with multiple sources (no trailing comma after last item): -# RSS_FEED_SOURCES='[{"id":"prowler-releases","name":"Prowler Releases","type":"github_releases","url":"https://github.com/prowler-cloud/prowler/releases.atom","enabled":true},{"id":"prowler-blog","name":"Prowler Blog","type":"blog","url":"https://prowler.com/blog/rss","enabled":false}]' \ No newline at end of file +# RSS_FEED_SOURCES='[{"id":"prowler-releases","name":"Prowler Releases","type":"github_releases","url":"https://github.com/prowler-cloud/prowler/releases.atom","enabled":true},{"id":"prowler-blog","name":"Prowler Blog","type":"blog","url":"https://prowler.com/blog/rss","enabled":false}]' + diff --git a/.github/actions/slack-notification/action.yml b/.github/actions/slack-notification/action.yml index d073af9d53..1427fed3e0 100644 --- a/.github/actions/slack-notification/action.yml +++ b/.github/actions/slack-notification/action.yml @@ -12,7 +12,7 @@ inputs: required: false default: '' step-outcome: - description: 'Outcome of a step to determine status (success/failure) - automatically sets STATUS_EMOJI, STATUS_TEXT, and STATUS_COLOR env vars' + description: 'Outcome of a step to determine status (success/failure) - automatically sets STATUS_TEXT and STATUS_COLOR env vars' required: false default: '' outputs: @@ -27,16 +27,14 @@ runs: shell: bash run: | if [[ "${{ inputs.step-outcome }}" == "success" ]]; then - echo "STATUS_EMOJI=[✓]" >> $GITHUB_ENV - echo "STATUS_TEXT=succeeded" >> $GITHUB_ENV - echo "STATUS_COLOR=6aa84f" >> $GITHUB_ENV + echo "STATUS_TEXT=Completed" >> $GITHUB_ENV + echo "STATUS_COLOR=#6aa84f" >> $GITHUB_ENV elif [[ "${{ inputs.step-outcome }}" == "failure" ]]; then - echo "STATUS_EMOJI=[✗]" >> $GITHUB_ENV - echo "STATUS_TEXT=failed" >> $GITHUB_ENV - echo "STATUS_COLOR=fc3434" >> $GITHUB_ENV + 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 + echo "STATUS_COLOR=#dbab09" >> $GITHUB_ENV fi - name: Send Slack notification (new message) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 94122d8349..497c4d6214 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -22,6 +22,13 @@ Please add a detailed description of how to review this PR. - [ ] Review if is needed to change the [Readme.md](https://github.com/prowler-cloud/prowler/blob/master/README.md) - [ ] Ensure new entries are added to [CHANGELOG.md](https://github.com/prowler-cloud/prowler/blob/master/prowler/CHANGELOG.md), if applicable. +#### UI +- [ ] All issue/task requirements work as expected on the UI +- [ ] Screenshots/Video of the functionality flow (if applicable) - Mobile (X < 640px) +- [ ] Screenshots/Video of the functionality flow (if applicable) - Table (640px > X < 1024px) +- [ ] Screenshots/Video of the functionality flow (if applicable) - Desktop (X > 1024px) +- [ ] Ensure new entries are added to [CHANGELOG.md](https://github.com/prowler-cloud/prowler/blob/master/ui/CHANGELOG.md), if applicable. + #### API - [ ] Verify if API specs need to be regenerated. - [ ] Check if version updates are required (e.g., specs, Poetry, etc.). diff --git a/.github/scripts/slack-messages/container-release-completed.json b/.github/scripts/slack-messages/container-release-completed.json index 6158809c1f..c1fc147191 100644 --- a/.github/scripts/slack-messages/container-release-completed.json +++ b/.github/scripts/slack-messages/container-release-completed.json @@ -1,4 +1,17 @@ { "channel": "${{ env.SLACK_CHANNEL_ID }}", - "text": "${{ env.STATUS_EMOJI }} ${{ env.COMPONENT }} container release ${{ env.RELEASE_TAG }} push ${{ env.STATUS_TEXT }} <${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}|View run>" + "attachments": [ + { + "color": "${{ env.STATUS_COLOR }}", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Status:*\n${{ env.STATUS_TEXT }}\n\n${{ env.COMPONENT }} container release ${{ env.RELEASE_TAG }} push ${{ env.STATUS_TEXT }}\n\n<${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}|View run>" + } + } + ] + } + ] } diff --git a/.github/scripts/slack-messages/container-release-started.json b/.github/scripts/slack-messages/container-release-started.json index a203fae913..f67129e3ba 100644 --- a/.github/scripts/slack-messages/container-release-started.json +++ b/.github/scripts/slack-messages/container-release-started.json @@ -1,4 +1,17 @@ { "channel": "${{ env.SLACK_CHANNEL_ID }}", - "text": "${{ env.COMPONENT }} container release ${{ env.RELEASE_TAG }} push started... <${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}|View run>" + "attachments": [ + { + "color": "${{ env.STATUS_COLOR }}", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*Status:*\nStarted\n\n${{ env.COMPONENT }} container release ${{ env.RELEASE_TAG }} push started...\n\n<${{ env.GITHUB_SERVER_URL }}/${{ env.GITHUB_REPOSITORY }}/actions/runs/${{ env.GITHUB_RUN_ID }}|View run>" + } + } + ] + } + ] } diff --git a/.github/workflows/api-code-quality.yml b/.github/workflows/api-code-quality.yml index 2c52e532ba..a9dddaa3aa 100644 --- a/.github/workflows/api-code-quality.yml +++ b/.github/workflows/api-code-quality.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-code-quality.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-code-quality.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -45,6 +39,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: | + api/** + .github/workflows/api-code-quality.yml files_ignore: | api/docs/** api/README.md diff --git a/.github/workflows/api-codeql.yml b/.github/workflows/api-codeql.yml index f01e969134..16ea82538e 100644 --- a/.github/workflows/api-codeql.yml +++ b/.github/workflows/api-codeql.yml @@ -45,12 +45,12 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Initialize CodeQL - uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/api-codeql-config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 with: category: '/language:${{ matrix.language }}' diff --git a/.github/workflows/api-container-checks.yml b/.github/workflows/api-container-checks.yml index 0b9f5a28bc..d069b0d5a6 100644 --- a/.github/workflows/api-container-checks.yml +++ b/.github/workflows/api-container-checks.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-container-checks.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-container-checks.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -64,6 +58,7 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: api/** files_ignore: | api/docs/** api/README.md diff --git a/.github/workflows/api-security.yml b/.github/workflows/api-security.yml index 126b957ed0..33134ec9c9 100644 --- a/.github/workflows/api-security.yml +++ b/.github/workflows/api-security.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-security.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-security.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -45,6 +39,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: | + api/** + .github/workflows/api-security.yml files_ignore: | api/docs/** api/README.md diff --git a/.github/workflows/api-tests.yml b/.github/workflows/api-tests.yml index 3f827d8283..daeb79abac 100644 --- a/.github/workflows/api-tests.yml +++ b/.github/workflows/api-tests.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-tests.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'api/**' - - '.github/workflows/api-tests.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -85,6 +79,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: | + api/** + .github/workflows/api-tests.yml files_ignore: | api/docs/** api/README.md diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index f8df9a9abc..974d919fc6 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -38,7 +38,7 @@ jobs: - name: Backport PR if: steps.label_check.outputs.label_check == 'success' - uses: sorenlouv/backport-github-action@ad888e978060bc1b2798690dd9d03c4036560947 # v9.5.1 + uses: sorenlouv/backport-github-action@516854e7c9f962b9939085c9a92ea28411d1ae90 # v10.2.0 with: github_token: ${{ secrets.PROWLER_BOT_ACCESS_TOKEN }} auto_backport_label_prefix: ${{ env.BACKPORT_LABEL_PREFIX }} diff --git a/.github/workflows/conventional-commit.yml b/.github/workflows/conventional-commit.yml index c5ba446edf..58e1653b74 100644 --- a/.github/workflows/conventional-commit.yml +++ b/.github/workflows/conventional-commit.yml @@ -26,6 +26,6 @@ jobs: steps: - name: Check PR title format - uses: agenthunt/conventional-commit-checker-action@9e552d650d0e205553ec7792d447929fc78e012b # v2.0.0 + uses: agenthunt/conventional-commit-checker-action@f1823f632e95a64547566dcd2c7da920e67117ad # v2.0.1 with: pr-title-regex: '^(feat|fix|docs|style|refactor|perf|test|chore|build|ci|revert)(\([^)]+\))?!?: .+' diff --git a/.github/workflows/find-secrets.yml b/.github/workflows/find-secrets.yml index 6428cf8f08..80b49e3279 100644 --- a/.github/workflows/find-secrets.yml +++ b/.github/workflows/find-secrets.yml @@ -28,6 +28,6 @@ jobs: fetch-depth: 0 - name: Scan for secrets with TruffleHog - uses: trufflesecurity/trufflehog@ad6fc8fb446b8fafbf7ea8193d2d6bfd42f45690 # v3.90.11 + uses: trufflesecurity/trufflehog@b84c3d14d189e16da175e2c27fa8136603783ffc # v3.90.12 with: extra_args: '--results=verified,unknown' diff --git a/.github/workflows/labeler-community.yml b/.github/workflows/labeler-community.yml index ee157cc7d2..c6115b4d30 100644 --- a/.github/workflows/labeler-community.yml +++ b/.github/workflows/labeler-community.yml @@ -40,4 +40,6 @@ jobs: GH_TOKEN: ${{ github.token }} run: | echo "Adding 'community' label to PR #$PR_NUMBER" - gh pr edit "$PR_NUMBER" --add-label community + gh api /repos/${{ github.repository }}/issues/${{ github.event.number }}/labels \ + -X POST \ + -f labels[]='community' diff --git a/.github/workflows/mcp-container-checks.yml b/.github/workflows/mcp-container-checks.yml index f93ed9023c..3310cd8c5a 100644 --- a/.github/workflows/mcp-container-checks.yml +++ b/.github/workflows/mcp-container-checks.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'mcp_server/**' - - '.github/workflows/mcp-container-checks.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'mcp_server/**' - - '.github/workflows/mcp-container-checks.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -63,6 +57,7 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: mcp_server/** files_ignore: | mcp_server/README.md mcp_server/CHANGELOG.md diff --git a/.github/workflows/pr-check-changelog.yml b/.github/workflows/pr-check-changelog.yml index f8de212e2a..d1a3220402 100644 --- a/.github/workflows/pr-check-changelog.yml +++ b/.github/workflows/pr-check-changelog.yml @@ -83,7 +83,7 @@ jobs: - name: Update PR comment with changelog status if: github.event.pull_request.head.repo.full_name == github.repository - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 with: issue-number: ${{ github.event.pull_request.number }} comment-id: ${{ steps.find-comment.outputs.comment-id }} diff --git a/.github/workflows/pr-conflict-checker.yml b/.github/workflows/pr-conflict-checker.yml index 3761d252a3..c46fafc2d0 100644 --- a/.github/workflows/pr-conflict-checker.yml +++ b/.github/workflows/pr-conflict-checker.yml @@ -97,7 +97,7 @@ jobs: body-includes: '' - name: Create or update comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 with: comment-id: ${{ steps.find-comment.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 55b7d2e441..ae039bd5a6 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -47,7 +47,7 @@ jobs: git config --global user.name 'prowler-bot' git config --global user.email '179230569+prowler-bot@users.noreply.github.com' - - name: Parse version and read changelogs + - name: Parse version and determine branch run: | # Validate version format (reusing pattern from sdk-bump-version.yml) if [[ $PROWLER_VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then @@ -64,66 +64,83 @@ jobs: BRANCH_NAME="v${MAJOR_VERSION}.${MINOR_VERSION}" echo "BRANCH_NAME=${BRANCH_NAME}" >> "${GITHUB_ENV}" - # Function to extract the latest version from changelog - extract_latest_version() { - local changelog_file="$1" - if [ -f "$changelog_file" ]; then - # Extract the first version entry (most recent) from changelog - # Format: ## [version] (1.2.3) or ## [vversion] (v1.2.3) - local version=$(grep -m 1 '^## \[' "$changelog_file" | sed 's/^## \[\(.*\)\].*/\1/' | sed 's/^v//' | tr -d '[:space:]') - echo "$version" - else - echo "" - fi - } - - # Read actual versions from changelogs (source of truth) - UI_VERSION=$(extract_latest_version "ui/CHANGELOG.md") - API_VERSION=$(extract_latest_version "api/CHANGELOG.md") - SDK_VERSION=$(extract_latest_version "prowler/CHANGELOG.md") - MCP_VERSION=$(extract_latest_version "mcp_server/CHANGELOG.md") - - echo "UI_VERSION=${UI_VERSION}" >> "${GITHUB_ENV}" - echo "API_VERSION=${API_VERSION}" >> "${GITHUB_ENV}" - echo "SDK_VERSION=${SDK_VERSION}" >> "${GITHUB_ENV}" - echo "MCP_VERSION=${MCP_VERSION}" >> "${GITHUB_ENV}" - - if [ -n "$UI_VERSION" ]; then - echo "Read UI version from changelog: $UI_VERSION" - else - echo "Warning: No UI version found in ui/CHANGELOG.md" - fi - - if [ -n "$API_VERSION" ]; then - echo "Read API version from changelog: $API_VERSION" - else - echo "Warning: No API version found in api/CHANGELOG.md" - fi - - if [ -n "$SDK_VERSION" ]; then - echo "Read SDK version from changelog: $SDK_VERSION" - else - echo "Warning: No SDK version found in prowler/CHANGELOG.md" - fi - - if [ -n "$MCP_VERSION" ]; then - echo "Read MCP version from changelog: $MCP_VERSION" - else - echo "Warning: No MCP version found in mcp_server/CHANGELOG.md" - fi - echo "Prowler version: $PROWLER_VERSION" echo "Branch name: $BRANCH_NAME" - echo "UI version: $UI_VERSION" - echo "API version: $API_VERSION" - echo "SDK version: $SDK_VERSION" - echo "MCP version: $MCP_VERSION" echo "Is minor release: $([ $PATCH_VERSION -eq 0 ] && echo 'true' || echo 'false')" else echo "Invalid version syntax: '$PROWLER_VERSION' (must be N.N.N)" >&2 exit 1 fi + - name: Checkout release branch + run: | + echo "Checking out branch $BRANCH_NAME for release $PROWLER_VERSION..." + if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then + echo "Branch $BRANCH_NAME exists locally, checking out..." + git checkout "$BRANCH_NAME" + elif git show-ref --verify --quiet "refs/remotes/origin/$BRANCH_NAME"; then + echo "Branch $BRANCH_NAME exists remotely, checking out..." + git checkout -b "$BRANCH_NAME" "origin/$BRANCH_NAME" + else + echo "ERROR: Branch $BRANCH_NAME does not exist. For minor releases (X.Y.0), create it manually first. For patch releases (X.Y.Z), the branch should already exist." + exit 1 + fi + + - name: Read changelog versions from release branch + run: | + # Function to extract the latest version from changelog + extract_latest_version() { + local changelog_file="$1" + if [ -f "$changelog_file" ]; then + # Extract the first version entry (most recent) from changelog + # Format: ## [version] (1.2.3) or ## [vversion] (v1.2.3) + local version=$(grep -m 1 '^## \[' "$changelog_file" | sed 's/^## \[\(.*\)\].*/\1/' | sed 's/^v//' | tr -d '[:space:]') + echo "$version" + else + echo "" + fi + } + + # Read actual versions from changelogs (source of truth) + UI_VERSION=$(extract_latest_version "ui/CHANGELOG.md") + API_VERSION=$(extract_latest_version "api/CHANGELOG.md") + SDK_VERSION=$(extract_latest_version "prowler/CHANGELOG.md") + MCP_VERSION=$(extract_latest_version "mcp_server/CHANGELOG.md") + + echo "UI_VERSION=${UI_VERSION}" >> "${GITHUB_ENV}" + echo "API_VERSION=${API_VERSION}" >> "${GITHUB_ENV}" + echo "SDK_VERSION=${SDK_VERSION}" >> "${GITHUB_ENV}" + echo "MCP_VERSION=${MCP_VERSION}" >> "${GITHUB_ENV}" + + if [ -n "$UI_VERSION" ]; then + echo "Read UI version from changelog: $UI_VERSION" + else + echo "Warning: No UI version found in ui/CHANGELOG.md" + fi + + if [ -n "$API_VERSION" ]; then + echo "Read API version from changelog: $API_VERSION" + else + echo "Warning: No API version found in api/CHANGELOG.md" + fi + + if [ -n "$SDK_VERSION" ]; then + echo "Read SDK version from changelog: $SDK_VERSION" + else + echo "Warning: No SDK version found in prowler/CHANGELOG.md" + fi + + if [ -n "$MCP_VERSION" ]; then + echo "Read MCP version from changelog: $MCP_VERSION" + else + echo "Warning: No MCP version found in mcp_server/CHANGELOG.md" + fi + + echo "UI version: $UI_VERSION" + echo "API version: $API_VERSION" + echo "SDK version: $SDK_VERSION" + echo "MCP version: $MCP_VERSION" + - name: Extract and combine changelog entries run: | set -e @@ -255,21 +272,6 @@ jobs: echo "Combined changelog preview:" cat combined_changelog.md - - name: Checkout release branch for patch release - if: ${{ env.PATCH_VERSION != '0' }} - run: | - echo "Patch release detected, checking out existing branch $BRANCH_NAME..." - if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then - echo "Branch $BRANCH_NAME exists locally, checking out..." - git checkout "$BRANCH_NAME" - elif git show-ref --verify --quiet "refs/remotes/origin/$BRANCH_NAME"; then - echo "Branch $BRANCH_NAME exists remotely, checking out..." - git checkout -b "$BRANCH_NAME" "origin/$BRANCH_NAME" - else - echo "ERROR: Branch $BRANCH_NAME should exist for patch release $PROWLER_VERSION" - exit 1 - fi - - name: Verify SDK version in pyproject.toml run: | CURRENT_VERSION=$(grep '^version = ' pyproject.toml | sed -E 's/version = "([^"]+)"/\1/' | tr -d '[:space:]') @@ -323,18 +325,6 @@ jobs: fi echo "✓ api/src/backend/api/v1/views.py version: $CURRENT_API_VERSION" - - name: Checkout release branch for minor release - if: ${{ env.PATCH_VERSION == '0' }} - run: | - echo "Minor release detected (patch = 0), checking out existing branch $BRANCH_NAME..." - if git show-ref --verify --quiet "refs/remotes/origin/$BRANCH_NAME"; then - echo "Branch $BRANCH_NAME exists remotely, checking out..." - git checkout -b "$BRANCH_NAME" "origin/$BRANCH_NAME" - else - echo "ERROR: Branch $BRANCH_NAME should exist for minor release $PROWLER_VERSION. Please create it manually first." - exit 1 - fi - - name: Update API prowler dependency for minor release if: ${{ env.PATCH_VERSION == '0' }} run: | @@ -392,7 +382,7 @@ jobs: no-changelog - name: Create draft release - uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 + uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2.4.1 with: tag_name: ${{ env.PROWLER_VERSION }} name: Prowler ${{ env.PROWLER_VERSION }} diff --git a/.github/workflows/sdk-code-quality.yml b/.github/workflows/sdk-code-quality.yml index 943f456a4c..b32324d8cb 100644 --- a/.github/workflows/sdk-code-quality.yml +++ b/.github/workflows/sdk-code-quality.yml @@ -5,22 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'pyproject.toml' - - 'poetry.lock' - - '.github/workflows/sdk-code-quality.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'pyproject.toml' - - 'poetry.lock' - - '.github/workflows/sdk-code-quality.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -49,7 +37,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: ./** files_ignore: | + .github/** prowler/CHANGELOG.md docs/** permissions/** diff --git a/.github/workflows/sdk-codeql.yml b/.github/workflows/sdk-codeql.yml index e092b8ae1a..590ba52d34 100644 --- a/.github/workflows/sdk-codeql.yml +++ b/.github/workflows/sdk-codeql.yml @@ -52,12 +52,12 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Initialize CodeQL - uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/sdk-codeql-config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 with: category: '/language:${{ matrix.language }}' diff --git a/.github/workflows/sdk-container-checks.yml b/.github/workflows/sdk-container-checks.yml index 3e843ca171..4e8a7cf2ad 100644 --- a/.github/workflows/sdk-container-checks.yml +++ b/.github/workflows/sdk-container-checks.yml @@ -5,20 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'Dockerfile' - - '.github/workflows/sdk-container-checks.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'Dockerfile' - - '.github/workflows/sdk-container-checks.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -69,7 +59,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: ./** files_ignore: | + .github/** prowler/CHANGELOG.md docs/** permissions/** diff --git a/.github/workflows/sdk-refresh-aws-services-regions.yml b/.github/workflows/sdk-refresh-aws-services-regions.yml index 4df220fc49..884b677294 100644 --- a/.github/workflows/sdk-refresh-aws-services-regions.yml +++ b/.github/workflows/sdk-refresh-aws-services-regions.yml @@ -39,7 +39,7 @@ jobs: run: pip install boto3 - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@a03048d87541d1d9fcf2ecf528a4a65ba9bd7838 # v5.0.0 + uses: aws-actions/configure-aws-credentials@00943011d9042930efac3dcd3a170e4273319bc8 # v5.1.0 with: aws-region: ${{ env.AWS_REGION }} role-to-assume: ${{ secrets.DEV_IAM_ROLE_ARN }} diff --git a/.github/workflows/sdk-security.yml b/.github/workflows/sdk-security.yml index c4fbf9a2a3..a15bd2539f 100644 --- a/.github/workflows/sdk-security.yml +++ b/.github/workflows/sdk-security.yml @@ -5,22 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'pyproject.toml' - - 'poetry.lock' - - '.github/workflows/sdk-security.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'pyproject.toml' - - 'poetry.lock' - - '.github/workflows/sdk-security.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -42,7 +30,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: ./** files_ignore: | + .github/** prowler/CHANGELOG.md docs/** permissions/** diff --git a/.github/workflows/sdk-tests.yml b/.github/workflows/sdk-tests.yml index 5356bf857b..b01c5e7778 100644 --- a/.github/workflows/sdk-tests.yml +++ b/.github/workflows/sdk-tests.yml @@ -5,22 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'pyproject.toml' - - 'poetry.lock' - - '.github/workflows/sdk-tests.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'prowler/**' - - 'tests/**' - - 'pyproject.toml' - - 'poetry.lock' - - '.github/workflows/sdk-tests.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -49,7 +37,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: ./** files_ignore: | + .github/** prowler/CHANGELOG.md docs/** permissions/** diff --git a/.github/workflows/ui-codeql.yml b/.github/workflows/ui-codeql.yml index 798aa39636..2b55cf673c 100644 --- a/.github/workflows/ui-codeql.yml +++ b/.github/workflows/ui-codeql.yml @@ -48,12 +48,12 @@ jobs: uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - name: Initialize CodeQL - uses: github/codeql-action/init@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/init@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 with: languages: ${{ matrix.language }} config-file: ./.github/codeql/ui-codeql-config.yml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@3599b3baa15b485a2e49ef411a7a4bb2452e7f93 # v3.30.5 + uses: github/codeql-action/analyze@0499de31b99561a6d14a36a5f662c2a54f91beee # v4.31.2 with: category: '/language:${{ matrix.language }}' diff --git a/.github/workflows/ui-container-checks.yml b/.github/workflows/ui-container-checks.yml index 8675fff7b8..e436c3974a 100644 --- a/.github/workflows/ui-container-checks.yml +++ b/.github/workflows/ui-container-checks.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'ui/**' - - '.github/workflows/ui-container-checks.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'ui/**' - - '.github/workflows/ui-container-checks.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -64,6 +58,7 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: ui/** files_ignore: | ui/CHANGELOG.md ui/README.md diff --git a/.github/workflows/ui-e2e-tests.yml b/.github/workflows/ui-e2e-tests.yml index 87be96808d..790a4a6825 100644 --- a/.github/workflows/ui-e2e-tests.yml +++ b/.github/workflows/ui-e2e-tests.yml @@ -95,7 +95,7 @@ jobs: echo "All database fixtures loaded successfully!" ' - name: Setup Node.js environment - uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version: '20.x' cache: 'npm' diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index fcc05f743a..a5a5b5fa17 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -5,16 +5,10 @@ on: branches: - 'master' - 'v5.*' - paths: - - 'ui/**' - - '.github/workflows/ui-tests.yml' pull_request: branches: - 'master' - 'v5.*' - paths: - - 'ui/**' - - '.github/workflows/ui-tests.yml' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -42,6 +36,9 @@ jobs: id: check-changes uses: tj-actions/changed-files@24d32ffd492484c1d75e0c0b894501ddb9d30d62 # v47.0.0 with: + files: | + ui/** + .github/workflows/ui-tests.yml files_ignore: | ui/CHANGELOG.md ui/README.md diff --git a/README.md b/README.md index baf226ec89..83af8dcfb7 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Prowler includes hundreds of built-in controls to ensure compliance with standar Prowler App is a web-based application that simplifies running Prowler across your cloud provider accounts. It provides a user-friendly interface to visualize the results and streamline your security assessments. -![Prowler App](docs/products/img/overview.png) +![Prowler App](docs/images/products/overview.png) >For more details, refer to the [Prowler App Documentation](https://docs.prowler.com/projects/prowler-open-source/en/latest/#prowler-app-installation) @@ -73,26 +73,26 @@ prowler ```console prowler dashboard ``` -![Prowler Dashboard](docs/products/img/dashboard.png) +![Prowler Dashboard](docs/images/products/dashboard.png) # Prowler at a Glance > [!Tip] > For the most accurate and up-to-date information about checks, services, frameworks, and categories, visit [**Prowler Hub**](https://hub.prowler.com). -| Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/compliance/) | [Categories](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/misc/#categories) | Support | Stage | Interface | -|---|---|---|---|---|---|---|---| -| AWS | 576 | 82 | 38 | 10 | Official | Stable | UI, API, CLI | -| GCP | 79 | 13 | 11 | 3 | Official | Stable | UI, API, CLI | -| Azure | 162 | 19 | 12 | 4 | Official | Stable | UI, API, CLI | -| Kubernetes | 83 | 7 | 5 | 7 | Official | Stable | UI, API, CLI | +| Provider | Checks | Services | [Compliance Frameworks](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/compliance/) | [Categories](https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/misc/#categories) | Support | Interface | +|---|---|---|---|---|---|---| +| AWS | 576 | 82 | 38 | 10 | Official | UI, API, CLI | +| GCP | 79 | 13 | 12 | 3 | Official | UI, API, CLI | +| Azure | 162 | 19 | 12 | 4 | Official | UI, API, CLI | +| Kubernetes | 83 | 7 | 5 | 7 | Official | UI, API, CLI | | GitHub | 17 | 2 | 1 | 0 | Official | Stable | UI, API, CLI | -| M365 | 70 | 7 | 3 | 2 | Official | Stable | UI, API, CLI | -| OCI | 51 | 13 | 1 | 10 | Official | Stable | UI, API, CLI | -| IaC | [See `trivy` docs.](https://trivy.dev/latest/docs/coverage/iac/) | N/A | N/A | N/A | Official | Beta | CLI | -| MongoDB Atlas | 10 | 3 | 0 | 0 | Official | Beta | CLI | -| LLM | [See `promptfoo` docs.](https://www.promptfoo.dev/docs/red-team/plugins/) | N/A | N/A | N/A | Official | Beta | CLI | -| NHN | 6 | 2 | 1 | 0 | Unofficial | Beta | CLI | +| M365 | 70 | 7 | 3 | 2 | Official | UI, API, CLI | +| OCI | 51 | 13 | 1 | 10 | Official | UI, API, CLI | +| IaC | [See `trivy` docs.](https://trivy.dev/latest/docs/coverage/iac/) | N/A | N/A | N/A | Official | UI, API, CLI | +| MongoDB Atlas | 10 | 3 | 0 | 0 | Official | CLI, API | +| LLM | [See `promptfoo` docs.](https://www.promptfoo.dev/docs/red-team/plugins/) | N/A | N/A | N/A | Official | CLI | +| NHN | 6 | 2 | 1 | 0 | Unofficial | CLI | > [!Note] > The numbers in the table are updated periodically. diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 8b36cb94a1..5e4720bcf9 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to the **Prowler API** are documented in this file. ## [1.15.0] (Prowler UNRELEASED) ### Added +- IaC (Infrastructure as Code) provider support for remote repositories [(#8751)](https://github.com/prowler-cloud/prowler/pull/8751) - Extend `GET /api/v1/providers` with provider-type filters and optional pagination disable to support the new Overview filters [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - New endpoint to retrieve the number of providers grouped by provider type [(#8975)](https://github.com/prowler-cloud/prowler/pull/8975) - Support for configuring multiple LLM providers [(#8772)](https://github.com/prowler-cloud/prowler/pull/8772) @@ -13,6 +14,7 @@ All notable changes to the **Prowler API** are documented in this file. - Support muting findings based on simple rules with custom reason [(#9051)](https://github.com/prowler-cloud/prowler/pull/9051) - Support C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) - Support for Amazon Bedrock and OpenAI compatible providers in Lighthouse AI [(#8957)](https://github.com/prowler-cloud/prowler/pull/8957) +- Support for MongoDB Atlas provider [(#9167)](https://github.com/prowler-cloud/prowler/pull/9167) --- diff --git a/api/Dockerfile b/api/Dockerfile index a3cfb21782..2d7883a957 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -5,6 +5,9 @@ LABEL maintainer="https://github.com/prowler-cloud/api" ARG POWERSHELL_VERSION=7.5.0 ENV POWERSHELL_VERSION=${POWERSHELL_VERSION} +ARG TRIVY_VERSION=0.66.0 +ENV TRIVY_VERSION=${TRIVY_VERSION} + # hadolint ignore=DL3008 RUN apt-get update && apt-get install -y --no-install-recommends \ wget \ @@ -36,6 +39,24 @@ RUN ARCH=$(uname -m) && \ ln -s /opt/microsoft/powershell/7/pwsh /usr/bin/pwsh && \ rm /tmp/powershell.tar.gz +# Install Trivy for IaC scanning +RUN ARCH=$(uname -m) && \ + if [ "$ARCH" = "x86_64" ]; then \ + TRIVY_ARCH="Linux-64bit" ; \ + elif [ "$ARCH" = "aarch64" ]; then \ + TRIVY_ARCH="Linux-ARM64" ; \ + else \ + echo "Unsupported architecture for Trivy: $ARCH" && exit 1 ; \ + fi && \ + wget --progress=dot:giga "https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_${TRIVY_ARCH}.tar.gz" -O /tmp/trivy.tar.gz && \ + tar zxf /tmp/trivy.tar.gz -C /tmp && \ + mv /tmp/trivy /usr/local/bin/trivy && \ + chmod +x /usr/local/bin/trivy && \ + rm /tmp/trivy.tar.gz && \ + # Create trivy cache directory with proper permissions + mkdir -p /tmp/.cache/trivy && \ + chmod 777 /tmp/.cache/trivy + # Add prowler user RUN addgroup --gid 1000 prowler && \ adduser --uid 1000 --gid 1000 --disabled-password --gecos "" prowler diff --git a/api/src/backend/api/migrations/0051_oraclecloud_provider.py b/api/src/backend/api/migrations/0051_oraclecloud_provider.py index fd96dfbcd5..022c022ea6 100644 --- a/api/src/backend/api/migrations/0051_oraclecloud_provider.py +++ b/api/src/backend/api/migrations/0051_oraclecloud_provider.py @@ -22,13 +22,13 @@ class Migration(migrations.Migration): ("kubernetes", "Kubernetes"), ("m365", "M365"), ("github", "GitHub"), - ("oci", "Oracle Cloud Infrastructure"), + ("oraclecloud", "Oracle Cloud Infrastructure"), ], default="aws", ), ), migrations.RunSQL( - "ALTER TYPE provider ADD VALUE IF NOT EXISTS 'oci';", + "ALTER TYPE provider ADD VALUE IF NOT EXISTS 'oraclecloud';", reverse_sql=migrations.RunSQL.noop, ), ] diff --git a/api/src/backend/api/migrations/0054_iac_provider.py b/api/src/backend/api/migrations/0054_iac_provider.py new file mode 100644 index 0000000000..3ba456b0cf --- /dev/null +++ b/api/src/backend/api/migrations/0054_iac_provider.py @@ -0,0 +1,35 @@ +# Generated by Django 5.1.10 on 2025-09-09 09:25 + +from django.db import migrations + +import api.db_utils + + +class Migration(migrations.Migration): + dependencies = [ + ("api", "0053_lighthouse_bedrock_openai_compatible"), + ] + + operations = [ + migrations.AlterField( + model_name="provider", + name="provider", + field=api.db_utils.ProviderEnumField( + choices=[ + ("aws", "AWS"), + ("azure", "Azure"), + ("gcp", "GCP"), + ("kubernetes", "Kubernetes"), + ("m365", "M365"), + ("github", "GitHub"), + ("oci", "Oracle Cloud Infrastructure"), + ("iac", "IaC"), + ], + default="aws", + ), + ), + migrations.RunSQL( + "ALTER TYPE provider ADD VALUE IF NOT EXISTS 'iac';", + reverse_sql=migrations.RunSQL.noop, + ), + ] diff --git a/api/src/backend/api/migrations/0055_mongodbatlas_provider.py b/api/src/backend/api/migrations/0055_mongodbatlas_provider.py new file mode 100644 index 0000000000..beb7a3946a --- /dev/null +++ b/api/src/backend/api/migrations/0055_mongodbatlas_provider.py @@ -0,0 +1,32 @@ +# Generated by Django 5.1.13 on 2025-11-05 08:37 + +from django.db import migrations + +import api.db_utils + + +class Migration(migrations.Migration): + dependencies = [ + ("api", "0054_iac_provider"), + ] + + operations = [ + migrations.AlterField( + model_name="provider", + name="provider", + field=api.db_utils.ProviderEnumField( + choices=[ + ("aws", "AWS"), + ("azure", "Azure"), + ("gcp", "GCP"), + ("kubernetes", "Kubernetes"), + ("m365", "M365"), + ("github", "GitHub"), + ("mongodbatlas", "MongoDB Atlas"), + ("iac", "IaC"), + ("oraclecloud", "Oracle Cloud Infrastructure"), + ], + default="aws", + ), + ), + ] diff --git a/api/src/backend/api/models.py b/api/src/backend/api/models.py index 3a0f1e9df2..7ca9594d5e 100644 --- a/api/src/backend/api/models.py +++ b/api/src/backend/api/models.py @@ -284,7 +284,9 @@ class Provider(RowLevelSecurityProtectedModel): KUBERNETES = "kubernetes", _("Kubernetes") M365 = "m365", _("M365") GITHUB = "github", _("GitHub") - OCI = "oci", _("Oracle Cloud Infrastructure") + MONGODBATLAS = "mongodbatlas", _("MongoDB Atlas") + IAC = "iac", _("IaC") + ORACLECLOUD = "oraclecloud", _("Oracle Cloud Infrastructure") @staticmethod def validate_aws_uid(value): @@ -356,14 +358,36 @@ class Provider(RowLevelSecurityProtectedModel): ) @staticmethod - def validate_oci_uid(value): + def validate_iac_uid(value): + # Validate that it's a valid repository URL (git URL format) + if not re.match( + r"^(https?://|git@|ssh://)[^\s/]+[^\s]*\.git$|^(https?://)[^\s/]+[^\s]*$", + value, + ): + raise ModelValidationError( + detail="IaC provider ID must be a valid repository URL (e.g., https://github.com/user/repo or https://github.com/user/repo.git).", + code="iac-uid", + pointer="/data/attributes/uid", + ) + + @staticmethod + def validate_oraclecloud_uid(value): if not re.match( r"^ocid1\.([a-z0-9_-]+)\.([a-z0-9_-]+)\.([a-z0-9_-]*)\.([a-z0-9]+)$", value ): raise ModelValidationError( detail="Oracle Cloud Infrastructure provider ID must be a valid tenancy OCID in the format: " "ocid1....", - code="oci-uid", + code="oraclecloud-uid", + pointer="/data/attributes/uid", + ) + + @staticmethod + def validate_mongodbatlas_uid(value): + if not re.match(r"^[0-9a-fA-F]{24}$", value): + raise ModelValidationError( + detail="MongoDB Atlas organization ID must be a 24-character hexadecimal string.", + code="mongodbatlas-uid", pointer="/data/attributes/uid", ) diff --git a/api/src/backend/api/specs/v1.yaml b/api/src/backend/api/specs/v1.yaml index 958e176472..e44dba0084 100644 --- a/api/src/backend/api/specs/v1.yaml +++ b/api/src/backend/api/specs/v1.yaml @@ -869,15 +869,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -885,22 +887,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -910,7 +915,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -1400,15 +1407,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -1416,22 +1425,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -1441,7 +1453,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -1839,15 +1853,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -1855,22 +1871,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -1880,7 +1899,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -2276,15 +2297,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -2292,22 +2315,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -2317,7 +2343,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -2701,15 +2729,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -2717,22 +2747,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -2742,7 +2775,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -4530,15 +4565,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -4546,22 +4583,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -4571,7 +4611,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -4711,15 +4753,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -4727,22 +4771,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -4752,7 +4799,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -4958,15 +5007,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -4974,22 +5025,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -4999,7 +5053,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -5685,15 +5741,17 @@ paths: name: filter[provider] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -5701,22 +5759,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -5726,14 +5787,15 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure @@ -5741,7 +5803,7 @@ paths: - github - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -5749,14 +5811,14 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure @@ -5764,7 +5826,7 @@ paths: - github - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -5774,7 +5836,7 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - name: filter[search] @@ -6372,15 +6434,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -6388,22 +6452,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -6413,7 +6480,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -6741,15 +6810,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -6757,22 +6828,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -6782,7 +6856,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -7011,15 +7087,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -7027,22 +7105,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -7052,7 +7133,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -7287,15 +7370,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -7303,22 +7388,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -7328,7 +7416,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -8126,15 +8216,17 @@ paths: name: filter[provider_type] schema: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas + - iac - kubernetes - m365 - - oci + - oraclecloud description: |- * `aws` - AWS * `azure` - Azure @@ -8142,22 +8234,25 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure - in: query name: filter[provider_type__in] schema: type: array items: type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 enum: - aws - azure - gcp - github + - mongodbatlas - kubernetes - m365 - - oci + - oraclecloud description: |- Multiple values may be separated by commas. @@ -8167,7 +8262,9 @@ paths: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `iac` - IaC + * `oraclecloud` - Oracle Cloud Infrastructure explode: false style: form - in: query @@ -14188,7 +14285,7 @@ components: type: string description: GitHub OAuth App token for authentication. required: - - oauth_app_token + - oauth_app_token - type: object title: GitHub App Credentials properties: @@ -14201,6 +14298,29 @@ components: required: - github_app_id - github_app_key + - type: object + title: MongoDB Atlas API Key + properties: + atlas_public_key: + type: string + description: MongoDB Atlas API public key. + atlas_private_key: + type: string + description: MongoDB Atlas API private key. + required: + - atlas_public_key + - atlas_private_key + - type: object + title: IaC Repository Credentials + properties: + repository_url: + type: string + description: Repository URL to scan for IaC files. + access_token: + type: string + description: Optional access token for private repositories. + required: + - repository_url - type: object title: Oracle Cloud Infrastructure (OCI) API Key Credentials properties: @@ -15228,7 +15348,8 @@ components: - kubernetes - m365 - github - - oci + - mongodbatlas + - oraclecloud type: string description: |- * `aws` - AWS @@ -15237,8 +15358,9 @@ components: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure - x-spec-enum-id: 6f034074d7104650 + * `mongodbatlas` - MongoDB Atlas + * `oraclecloud` - Oracle Cloud Infrastructure + x-spec-enum-id: 7087703783970b51 uid: type: string title: Unique identifier for the provider, set by the provider @@ -15350,9 +15472,10 @@ components: - kubernetes - m365 - github - - oci + - mongodbatlas + - oraclecloud type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 description: |- Type of provider to create. @@ -15362,12 +15485,13 @@ components: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `oraclecloud` - Oracle Cloud Infrastructure uid: type: string title: Unique identifier for the provider, set by the provider description: Unique identifier for the provider, set by the provider, - e.g. AWS account ID, Azure subscription ID, GCP project ID, etc. + e.g. AWS account ID, Azure subscription ID, GCP project ID, MongoDB Atlas organization ID, etc. maxLength: 250 minLength: 3 required: @@ -15406,9 +15530,10 @@ components: - kubernetes - m365 - github - - oci + - mongodbatlas + - oraclecloud type: string - x-spec-enum-id: 6f034074d7104650 + x-spec-enum-id: 7087703783970b51 description: |- Type of provider to create. @@ -15418,13 +15543,14 @@ components: * `kubernetes` - Kubernetes * `m365` - M365 * `github` - GitHub - * `oci` - Oracle Cloud Infrastructure + * `mongodbatlas` - MongoDB Atlas + * `oraclecloud` - Oracle Cloud Infrastructure uid: type: string minLength: 3 title: Unique identifier for the provider, set by the provider description: Unique identifier for the provider, set by the provider, - e.g. AWS account ID, Azure subscription ID, GCP project ID, etc. + e.g. AWS account ID, Azure subscription ID, GCP project ID, MongoDB Atlas organization ID, etc. maxLength: 250 required: - uid @@ -16127,6 +16253,17 @@ components: required: - github_app_id - github_app_key + - type: object + title: IaC Repository Credentials + properties: + repository_url: + type: string + description: Repository URL to scan for IaC files. + access_token: + type: string + description: Optional access token for private repositories. + required: + - repository_url - type: object title: Oracle Cloud Infrastructure (OCI) API Key Credentials properties: @@ -16427,6 +16564,17 @@ components: required: - github_app_id - github_app_key + - type: object + title: IaC Repository Credentials + properties: + repository_url: + type: string + description: Repository URL to scan for IaC files. + access_token: + type: string + description: Optional access token for private repositories. + required: + - repository_url - type: object title: Oracle Cloud Infrastructure (OCI) API Key Credentials properties: @@ -16745,6 +16893,17 @@ components: required: - github_app_id - github_app_key + - type: object + title: IaC Repository Credentials + properties: + repository_url: + type: string + description: Repository URL to scan for IaC files. + access_token: + type: string + description: Optional access token for private repositories. + required: + - repository_url - type: object title: Oracle Cloud Infrastructure (OCI) API Key Credentials properties: diff --git a/api/src/backend/api/tests/test_utils.py b/api/src/backend/api/tests/test_utils.py index 4926d722b0..d67df93ff5 100644 --- a/api/src/backend/api/tests/test_utils.py +++ b/api/src/backend/api/tests/test_utils.py @@ -20,9 +20,11 @@ from prowler.providers.aws.aws_provider import AwsProvider from prowler.providers.aws.lib.security_hub.security_hub import SecurityHubConnection from prowler.providers.azure.azure_provider import AzureProvider from prowler.providers.gcp.gcp_provider import GcpProvider +from prowler.providers.github.github_provider import GithubProvider from prowler.providers.kubernetes.kubernetes_provider import KubernetesProvider from prowler.providers.m365.m365_provider import M365Provider -from prowler.providers.oraclecloud.oci_provider import OciProvider +from prowler.providers.mongodbatlas.mongodbatlas_provider import MongodbatlasProvider +from prowler.providers.oraclecloud.oraclecloud_provider import OraclecloudProvider class TestMergeDicts: @@ -109,7 +111,9 @@ class TestReturnProwlerProvider: (Provider.ProviderChoices.AZURE.value, AzureProvider), (Provider.ProviderChoices.KUBERNETES.value, KubernetesProvider), (Provider.ProviderChoices.M365.value, M365Provider), - (Provider.ProviderChoices.OCI.value, OciProvider), + (Provider.ProviderChoices.GITHUB.value, GithubProvider), + (Provider.ProviderChoices.MONGODBATLAS.value, MongodbatlasProvider), + (Provider.ProviderChoices.ORACLECLOUD.value, OraclecloudProvider), ], ) def test_return_prowler_provider(self, provider_type, expected_provider): @@ -206,9 +210,13 @@ class TestGetProwlerProviderKwargs: {"organizations": ["provider_uid"]}, ), ( - Provider.ProviderChoices.OCI.value, + Provider.ProviderChoices.ORACLECLOUD.value, {}, ), + ( + Provider.ProviderChoices.MONGODBATLAS.value, + {"atlas_organization_id": "provider_uid"}, + ), ], ) def test_get_prowler_provider_kwargs(self, provider_type, expected_extra_kwargs): diff --git a/api/src/backend/api/tests/test_views.py b/api/src/backend/api/tests/test_views.py index 97e6002e00..8822bd9f12 100644 --- a/api/src/backend/api/tests/test_views.py +++ b/api/src/backend/api/tests/test_views.py @@ -1143,6 +1143,21 @@ class TestProviderViewSet: "uid": "a12345678901234567890123456789012345678", "alias": "Long Username", }, + { + "provider": "iac", + "uid": "https://github.com/user/repo.git", + "alias": "Git Repo", + }, + { + "provider": "iac", + "uid": "https://gitlab.com/user/project", + "alias": "GitLab Repo", + }, + { + "provider": "mongodbatlas", + "uid": "64b1d3c0e4b03b1234567890", + "alias": "Atlas Organization", + }, ] ), ) @@ -1292,6 +1307,51 @@ class TestProviderViewSet: "github-uid", "uid", ), + ( + { + "provider": "iac", + "uid": "not-a-url", + "alias": "test", + }, + "iac-uid", + "uid", + ), + ( + { + "provider": "iac", + "uid": "ftp://invalid-protocol.com/repo", + "alias": "test", + }, + "iac-uid", + "uid", + ), + ( + { + "provider": "iac", + "uid": "http://", + "alias": "test", + }, + "iac-uid", + "uid", + ), + ( + { + "provider": "mongodbatlas", + "uid": "64b1d3c0e4b03b123456789g", + "alias": "test", + }, + "mongodbatlas-uid", + "uid", + ), + ( + { + "provider": "mongodbatlas", + "uid": "1234", + "alias": "test", + }, + "mongodbatlas-uid", + "uid", + ), ] ), ) @@ -1465,22 +1525,22 @@ class TestProviderViewSet: ( "uid.icontains", "1", - 6, - ), # Updated: includes OCI provider with "1" in UID + 7, + ), ("alias", "aws_testing_1", 1), ("alias.icontains", "aws", 2), - ("inserted_at", TODAY, 7), # Updated: 7 providers now (added OCI) + ("inserted_at", TODAY, 8), ( "inserted_at.gte", "2024-01-01", - 7, - ), # Updated: 7 providers now (added OCI) + 8, + ), ("inserted_at.lte", "2024-01-01", 0), ( "updated_at.gte", "2024-01-01", - 7, - ), # Updated: 7 providers now (added OCI) + 8, + ), ("updated_at.lte", "2024-01-01", 0), ] ), @@ -1985,7 +2045,7 @@ class TestProviderSecretViewSet: ), # OCI with API key credentials (with key_content) ( - Provider.ProviderChoices.OCI.value, + Provider.ProviderChoices.ORACLECLOUD.value, ProviderSecret.TypeChoices.STATIC, { "user": "ocid1.user.oc1..aaaaaaaakldibrbov4ubh25aqdeiroklxjngwka7u6w7no3glmdq3n5sxtkq", @@ -1997,7 +2057,7 @@ class TestProviderSecretViewSet: ), # OCI with API key credentials (with key_file) ( - Provider.ProviderChoices.OCI.value, + Provider.ProviderChoices.ORACLECLOUD.value, ProviderSecret.TypeChoices.STATIC, { "user": "ocid1.user.oc1..aaaaaaaakldibrbov4ubh25aqdeiroklxjngwka7u6w7no3glmdq3n5sxtkq", @@ -2009,7 +2069,7 @@ class TestProviderSecretViewSet: ), # OCI with API key credentials (with passphrase) ( - Provider.ProviderChoices.OCI.value, + Provider.ProviderChoices.ORACLECLOUD.value, ProviderSecret.TypeChoices.STATIC, { "user": "ocid1.user.oc1..aaaaaaaakldibrbov4ubh25aqdeiroklxjngwka7u6w7no3glmdq3n5sxtkq", @@ -2020,6 +2080,15 @@ class TestProviderSecretViewSet: "pass_phrase": "my-secure-passphrase", }, ), + # MongoDB Atlas credentials + ( + Provider.ProviderChoices.MONGODBATLAS.value, + ProviderSecret.TypeChoices.STATIC, + { + "atlas_public_key": "public-key", + "atlas_private_key": "private-key", + }, + ), ], ) def test_provider_secrets_create_valid( diff --git a/api/src/backend/api/utils.py b/api/src/backend/api/utils.py index 0675c64d74..958f24b3f0 100644 --- a/api/src/backend/api/utils.py +++ b/api/src/backend/api/utils.py @@ -18,9 +18,11 @@ from prowler.providers.azure.azure_provider import AzureProvider from prowler.providers.common.models import Connection from prowler.providers.gcp.gcp_provider import GcpProvider from prowler.providers.github.github_provider import GithubProvider +from prowler.providers.iac.iac_provider import IacProvider from prowler.providers.kubernetes.kubernetes_provider import KubernetesProvider from prowler.providers.m365.m365_provider import M365Provider -from prowler.providers.oraclecloud.oci_provider import OciProvider +from prowler.providers.mongodbatlas.mongodbatlas_provider import MongodbatlasProvider +from prowler.providers.oraclecloud.oraclecloud_provider import OraclecloudProvider class CustomOAuth2Client(OAuth2Client): @@ -66,9 +68,11 @@ def return_prowler_provider( | AzureProvider | GcpProvider | GithubProvider + | IacProvider | KubernetesProvider | M365Provider - | OciProvider + | MongodbatlasProvider + | OraclecloudProvider ]: """Return the Prowler provider class based on the given provider type. @@ -76,7 +80,7 @@ def return_prowler_provider( provider (Provider): The provider object containing the provider type and associated secrets. Returns: - AwsProvider | AzureProvider | GcpProvider | GithubProvider | KubernetesProvider | M365Provider | OciProvider: The corresponding provider class. + AwsProvider | AzureProvider | GcpProvider | GithubProvider | IacProvider | KubernetesProvider | M365Provider | OraclecloudProvider | MongodbatlasProvider: The corresponding provider class. Raises: ValueError: If the provider type specified in `provider.provider` is not supported. @@ -94,8 +98,12 @@ def return_prowler_provider( prowler_provider = M365Provider case Provider.ProviderChoices.GITHUB.value: prowler_provider = GithubProvider - case Provider.ProviderChoices.OCI.value: - prowler_provider = OciProvider + case Provider.ProviderChoices.MONGODBATLAS.value: + prowler_provider = MongodbatlasProvider + case Provider.ProviderChoices.IAC.value: + prowler_provider = IacProvider + case Provider.ProviderChoices.ORACLECLOUD.value: + prowler_provider = OraclecloudProvider case _: raise ValueError(f"Provider type {provider.provider} not supported") return prowler_provider @@ -132,6 +140,21 @@ def get_prowler_provider_kwargs( **prowler_provider_kwargs, "organizations": [provider.uid], } + elif provider.provider == Provider.ProviderChoices.IAC.value: + # For IaC provider, uid contains the repository URL + # Extract the access token if present in the secret + prowler_provider_kwargs = { + "scan_repository_url": provider.uid, + } + if "access_token" in provider.secret.secret: + prowler_provider_kwargs["oauth_app_token"] = provider.secret.secret[ + "access_token" + ] + elif provider.provider == Provider.ProviderChoices.MONGODBATLAS.value: + prowler_provider_kwargs = { + **prowler_provider_kwargs, + "atlas_organization_id": provider.uid, + } if mutelist_processor: mutelist_content = mutelist_processor.configuration.get("Mutelist", {}) @@ -149,9 +172,11 @@ def initialize_prowler_provider( | AzureProvider | GcpProvider | GithubProvider + | IacProvider | KubernetesProvider | M365Provider - | OciProvider + | MongodbatlasProvider + | OraclecloudProvider ): """Initialize a Prowler provider instance based on the given provider type. @@ -160,8 +185,8 @@ def initialize_prowler_provider( mutelist_processor (Processor): The mutelist processor object containing the mutelist configuration. Returns: - AwsProvider | AzureProvider | GcpProvider | GithubProvider | KubernetesProvider | M365Provider | OciProvider: An instance of the corresponding provider class - (`AwsProvider`, `AzureProvider`, `GcpProvider`, `GithubProvider`, `KubernetesProvider`, `M365Provider` or `OciProvider`) initialized with the + AwsProvider | AzureProvider | GcpProvider | GithubProvider | IacProvider | KubernetesProvider | M365Provider | OraclecloudProvider | MongodbatlasProvider: An instance of the corresponding provider class + (`AwsProvider`, `AzureProvider`, `GcpProvider`, `GithubProvider`, `IacProvider`, `KubernetesProvider`, `M365Provider`, `OraclecloudProvider` or `MongodbatlasProvider`) initialized with the provider's secrets. """ prowler_provider = return_prowler_provider(provider) @@ -185,9 +210,23 @@ def prowler_provider_connection_test(provider: Provider) -> Connection: except Provider.secret.RelatedObjectDoesNotExist as secret_error: return Connection(is_connected=False, error=secret_error) - return prowler_provider.test_connection( - **prowler_provider_kwargs, provider_id=provider.uid, raise_on_exception=False - ) + # For IaC provider, construct the kwargs properly for test_connection + if provider.provider == Provider.ProviderChoices.IAC.value: + # Don't pass repository_url from secret, use scan_repository_url with the UID + iac_test_kwargs = { + "scan_repository_url": provider.uid, + "raise_on_exception": False, + } + # Add access_token if present in the secret + if "access_token" in prowler_provider_kwargs: + iac_test_kwargs["access_token"] = prowler_provider_kwargs["access_token"] + return prowler_provider.test_connection(**iac_test_kwargs) + else: + return prowler_provider.test_connection( + **prowler_provider_kwargs, + provider_id=provider.uid, + raise_on_exception=False, + ) def prowler_integration_connection_test(integration: Integration) -> Connection: diff --git a/api/src/backend/api/v1/serializer_utils/providers.py b/api/src/backend/api/v1/serializer_utils/providers.py index 8a47865fbd..4ec772e02f 100644 --- a/api/src/backend/api/v1/serializer_utils/providers.py +++ b/api/src/backend/api/v1/serializer_utils/providers.py @@ -239,6 +239,21 @@ from rest_framework_json_api import serializers }, "required": ["github_app_id", "github_app_key"], }, + { + "type": "object", + "title": "IaC Repository Credentials", + "properties": { + "repository_url": { + "type": "string", + "description": "Repository URL to scan for IaC files.", + }, + "access_token": { + "type": "string", + "description": "Optional access token for private repositories.", + }, + }, + "required": ["repository_url"], + }, { "type": "object", "title": "Oracle Cloud Infrastructure (OCI) API Key Credentials", @@ -274,6 +289,21 @@ from rest_framework_json_api import serializers }, "required": ["user", "fingerprint", "tenancy", "region"], }, + { + "type": "object", + "title": "MongoDB Atlas API Key", + "properties": { + "atlas_public_key": { + "type": "string", + "description": "MongoDB Atlas API public key.", + }, + "atlas_private_key": { + "type": "string", + "description": "MongoDB Atlas API private key.", + }, + }, + "required": ["atlas_public_key", "atlas_private_key"], + }, ] } ) diff --git a/api/src/backend/api/v1/serializers.py b/api/src/backend/api/v1/serializers.py index 1af474e6de..c79d305942 100644 --- a/api/src/backend/api/v1/serializers.py +++ b/api/src/backend/api/v1/serializers.py @@ -1362,12 +1362,16 @@ class BaseWriteProviderSecretSerializer(BaseWriteSerializer): serializer = GCPProviderSecret(data=secret) elif provider_type == Provider.ProviderChoices.GITHUB.value: serializer = GithubProviderSecret(data=secret) + elif provider_type == Provider.ProviderChoices.IAC.value: + serializer = IacProviderSecret(data=secret) elif provider_type == Provider.ProviderChoices.KUBERNETES.value: serializer = KubernetesProviderSecret(data=secret) elif provider_type == Provider.ProviderChoices.M365.value: serializer = M365ProviderSecret(data=secret) - elif provider_type == Provider.ProviderChoices.OCI.value: + elif provider_type == Provider.ProviderChoices.ORACLECLOUD.value: serializer = OracleCloudProviderSecret(data=secret) + elif provider_type == Provider.ProviderChoices.MONGODBATLAS.value: + serializer = MongoDBAtlasProviderSecret(data=secret) else: raise serializers.ValidationError( {"provider": f"Provider type not supported {provider_type}"} @@ -1464,6 +1468,14 @@ class GCPServiceAccountProviderSecret(serializers.Serializer): resource_name = "provider-secrets" +class MongoDBAtlasProviderSecret(serializers.Serializer): + atlas_public_key = serializers.CharField() + atlas_private_key = serializers.CharField() + + class Meta: + resource_name = "provider-secrets" + + class KubernetesProviderSecret(serializers.Serializer): kubeconfig_content = serializers.CharField() @@ -1481,6 +1493,14 @@ class GithubProviderSecret(serializers.Serializer): resource_name = "provider-secrets" +class IacProviderSecret(serializers.Serializer): + repository_url = serializers.CharField() + access_token = serializers.CharField(required=False) + + class Meta: + resource_name = "provider-secrets" + + class OracleCloudProviderSecret(serializers.Serializer): user = serializers.CharField() fingerprint = serializers.CharField() diff --git a/api/src/backend/conftest.py b/api/src/backend/conftest.py index 872dc60601..d5fa21a787 100644 --- a/api/src/backend/conftest.py +++ b/api/src/backend/conftest.py @@ -501,13 +501,28 @@ def providers_fixture(tenants_fixture): tenant_id=tenant.id, ) provider7 = Provider.objects.create( - provider="oci", + provider="oraclecloud", uid="ocid1.tenancy.oc1..aaaaaaaa3dwoazoox4q7wrvriywpokp5grlhgnkwtyt6dmwyou7no6mdmzda", alias="oci_testing", tenant_id=tenant.id, ) + provider8 = Provider.objects.create( + provider="mongodbatlas", + uid="64b1d3c0e4b03b1234567890", + alias="mongodbatlas_testing", + tenant_id=tenant.id, + ) - return provider1, provider2, provider3, provider4, provider5, provider6, provider7 + return ( + provider1, + provider2, + provider3, + provider4, + provider5, + provider6, + provider7, + provider8, + ) @pytest.fixture diff --git a/api/src/backend/tasks/jobs/export.py b/api/src/backend/tasks/jobs/export.py index b207285676..a3aee7bfc9 100644 --- a/api/src/backend/tasks/jobs/export.py +++ b/api/src/backend/tasks/jobs/export.py @@ -32,7 +32,7 @@ from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS from prowler.lib.outputs.compliance.cis.cis_github import GithubCIS from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS from prowler.lib.outputs.compliance.cis.cis_m365 import M365CIS -from prowler.lib.outputs.compliance.cis.cis_oci import OCICIS +from prowler.lib.outputs.compliance.cis.cis_oraclecloud import OracleCloudCIS from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS from prowler.lib.outputs.compliance.ens.ens_gcp import GCPENS @@ -113,8 +113,12 @@ COMPLIANCE_CLASS_MAP = { "github": [ (lambda name: name.startswith("cis_"), GithubCIS), ], - "oci": [ - (lambda name: name.startswith("cis_"), OCICIS), + "iac": [ + # IaC provider doesn't have specific compliance frameworks yet + # Trivy handles its own compliance checks + ], + "oraclecloud": [ + (lambda name: name.startswith("cis_"), OracleCloudCIS), ], } diff --git a/dashboard/compliance/hipaa_gcp.py b/dashboard/compliance/hipaa_gcp.py new file mode 100644 index 0000000000..b0a8eb6582 --- /dev/null +++ b/dashboard/compliance/hipaa_gcp.py @@ -0,0 +1,25 @@ +import warnings + +from dashboard.common_methods import get_section_containers_format3 + +warnings.filterwarnings("ignore") + + +def get_table(data): + + aux = data[ + [ + "REQUIREMENTS_ID", + "REQUIREMENTS_ATTRIBUTES_SECTION", + "REQUIREMENTS_DESCRIPTION", + "CHECKID", + "STATUS", + "REGION", + "ACCOUNTID", + "RESOURCEID", + ] + ].copy() + + return get_section_containers_format3( + aux, "REQUIREMENTS_ATTRIBUTES_SECTION", "REQUIREMENTS_ID" + ) diff --git a/docs/getting-started/installation/prowler-app.mdx b/docs/getting-started/installation/prowler-app.mdx index 4c49b8d4f0..f404180791 100644 --- a/docs/getting-started/installation/prowler-app.mdx +++ b/docs/getting-started/installation/prowler-app.mdx @@ -1,5 +1,5 @@ --- -title: 'Installation' +title: "Installation" --- ### Installation @@ -9,41 +9,40 @@ Prowler App supports multiple installation methods based on your environment. Refer to the [Prowler App Tutorial](/user-guide/tutorials/prowler-app) for detailed usage instructions. -Prowler configuration is based in `.env` files. Every version of Prowler can have differences on that file, so, please, use the file that corresponds with that version or repository branch or tag. - + Prowler configuration is based in `.env` files. Every version of Prowler can have differences on that file, so, please, use the file that corresponds with that version or repository branch or tag. + _Requirements_: - * `Docker Compose` installed: https://docs.docker.com/compose/install/. + - `Docker Compose` installed: https://docs.docker.com/compose/install/. _Commands_: - ``` bash - 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 + ```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" + curl -sLO "https://raw.githubusercontent.com/prowler-cloud/prowler/refs/tags/${VERSION}/.env" docker compose up -d ``` > Containers are built for `linux/amd64`. If your workstation's architecture is different, please set `DOCKER_DEFAULT_PLATFORM=linux/amd64` in your environment or use the `--platform linux/amd64` flag in the docker command. - _Requirements_: - * `git` installed. - * `poetry` installed: [poetry installation](https://python-poetry.org/docs/#installation). - * `npm` installed: [npm installation](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). - * `Docker Compose` installed: https://docs.docker.com/compose/install/. + - `git` installed. + - `poetry` installed: [poetry installation](https://python-poetry.org/docs/#installation). + - `npm` installed: [npm installation](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm). + - `Docker Compose` installed: https://docs.docker.com/compose/install/. - Make sure to have `api/.env` and `ui/.env.local` files with the required environment variables. You can find the required environment variables in the [`api/.env.template`](https://github.com/prowler-cloud/prowler/blob/master/api/.env.example) and [`ui/.env.template`](https://github.com/prowler-cloud/prowler/blob/master/ui/.env.template) files. + Make sure to have `api/.env` and `ui/.env.local` files with the required environment variables. You can find the required environment variables in the [`api/.env.template`](https://github.com/prowler-cloud/prowler/blob/master/api/.env.example) and [`ui/.env.template`](https://github.com/prowler-cloud/prowler/blob/master/ui/.env.template) files. - _Commands to run the API_: - ``` bash + ```bash git clone https://github.com/prowler-cloud/prowler \ cd prowler/api \ poetry install \ @@ -57,17 +56,15 @@ Prowler configuration is based in `.env` files. Every version of Prowler can hav ``` - Starting from Poetry v2.0.0, `poetry shell` has been deprecated in favor of `poetry env activate`. + Starting from Poetry v2.0.0, `poetry shell` has been deprecated in favor of `poetry env activate`. - If your poetry version is below 2.0.0 you must keep using `poetry shell` to activate your environment. - In case you have any doubts, consult the Poetry environment activation guide: https://python-poetry.org/docs/managing-environments/#activating-the-environment + If your poetry version is below 2.0.0 you must keep using `poetry shell` to activate your environment. In case you have any doubts, consult the Poetry environment activation guide: https://python-poetry.org/docs/managing-environments/#activating-the-environment - > Now, you can access the API documentation at http://localhost:8080/api/v1/docs. _Commands to run the API Worker_: - ``` bash + ```bash git clone https://github.com/prowler-cloud/prowler \ cd prowler/api \ poetry install \ @@ -80,7 +77,7 @@ Prowler configuration is based in `.env` files. Every version of Prowler can hav _Commands to run the API Scheduler_: - ``` bash + ```bash git clone https://github.com/prowler-cloud/prowler \ cd prowler/api \ poetry install \ @@ -93,7 +90,7 @@ Prowler configuration is based in `.env` files. Every version of Prowler can hav _Commands to run the UI_: - ``` bash + ```bash git clone https://github.com/prowler-cloud/prowler \ cd prowler/ui \ npm install \ @@ -104,10 +101,11 @@ Prowler configuration is based in `.env` files. Every version of Prowler can hav > Enjoy Prowler App at http://localhost:3000 by signing up with your email and password. - Google and GitHub authentication is only available in [Prowler Cloud](https://prowler.com). + Google and GitHub authentication is only available in [Prowler Cloud](https://prowler.com). + ### Update Prowler App Upgrade Prowler App installation using one of two options: @@ -129,13 +127,12 @@ docker compose pull --policy always The `--policy always` flag ensures that Docker pulls the latest images even if they already exist locally. - -**What Gets Preserved During Upgrade** - -Everything is preserved, nothing will be deleted after the update. + **What Gets Preserved During Upgrade** + Everything is preserved, nothing will be deleted after the update. + ### Troubleshooting If containers don't start, check logs for errors: @@ -155,7 +152,6 @@ docker compose pull docker compose up -d ``` - ### Container versions The available versions of Prowler CLI are the following: @@ -171,6 +167,5 @@ The available versions of Prowler CLI are the following: The container images are available here: - Prowler App: - - - [DockerHub - Prowler UI](https://hub.docker.com/r/prowlercloud/prowler-ui/tags) - - [DockerHub - Prowler API](https://hub.docker.com/r/prowlercloud/prowler-api/tags) + - [DockerHub - Prowler UI](https://hub.docker.com/r/prowlercloud/prowler-ui/tags) + - [DockerHub - Prowler API](https://hub.docker.com/r/prowlercloud/prowler-api/tags) diff --git a/docs/images/providers/add-iac-repo.png b/docs/images/providers/add-iac-repo.png new file mode 100644 index 0000000000..31981e7fd1 Binary files /dev/null and b/docs/images/providers/add-iac-repo.png differ diff --git a/docs/images/providers/iac-authentication.png b/docs/images/providers/iac-authentication.png new file mode 100644 index 0000000000..c6caad4ae1 Binary files /dev/null and b/docs/images/providers/iac-authentication.png differ diff --git a/docs/images/providers/iac-verify-connection.png b/docs/images/providers/iac-verify-connection.png new file mode 100644 index 0000000000..bc918f6c24 Binary files /dev/null and b/docs/images/providers/iac-verify-connection.png differ diff --git a/docs/images/providers/select-iac.png b/docs/images/providers/select-iac.png new file mode 100644 index 0000000000..1dc474cbe8 Binary files /dev/null and b/docs/images/providers/select-iac.png differ diff --git a/docs/introduction.mdx b/docs/introduction.mdx index 7c9bb623d0..616ba34f53 100644 --- a/docs/introduction.mdx +++ b/docs/introduction.mdx @@ -32,8 +32,8 @@ The supported providers right now are: | [M365](/user-guide/providers/microsoft365/getting-started-m365) | Official | UI, API, CLI | | [Github](/user-guide/providers/github/getting-started-github) | Official | UI, API, CLI | | [Oracle Cloud](/user-guide/providers/oci/getting-started-oci) | Official | UI, API, CLI | -| [Infra as Code](/user-guide/providers/iac/getting-started-iac) | Official | CLI | -| [MongoDB Atlas](/user-guide/providers/mongodbatlas/getting-started-mongodbatlas) | Official | CLI | +| [Infra as Code](/user-guide/providers/iac/getting-started-iac) | Official | UI, API, CLI | +| [MongoDB Atlas](/user-guide/providers/mongodbatlas/getting-started-mongodbatlas) | Official | CLI, API | | [LLM](/user-guide/providers/llm/getting-started-llm) | Official | CLI | | **NHN** | Unofficial | CLI | @@ -48,4 +48,4 @@ For more information about the checks and compliance of each provider visit [Pro Interested in contributing to Prowler? - \ No newline at end of file + diff --git a/docs/user-guide/providers/iac/getting-started-iac.mdx b/docs/user-guide/providers/iac/getting-started-iac.mdx index a3efb0f2df..315afafed4 100644 --- a/docs/user-guide/providers/iac/getting-started-iac.mdx +++ b/docs/user-guide/providers/iac/getting-started-iac.mdx @@ -1,6 +1,7 @@ --- title: "Getting Started with the IaC Provider" --- +import { VersionBadge } from "/snippets/version-badge.mdx" Prowler's Infrastructure as Code (IaC) provider enables scanning of local or remote infrastructure code for security and compliance issues using [Trivy](https://trivy.dev/). This provider supports a wide range of IaC frameworks, allowing assessment of code before deployment. @@ -22,8 +23,46 @@ The IaC provider leverages [Trivy](https://trivy.dev/latest/docs/scanner/vulnera - Mutelist logic ([filtering](https://trivy.dev/latest/docs/configuration/filtering/)) is handled by Trivy, not Prowler. - Results are output in the same formats as other Prowler providers (CSV, JSON, HTML, etc.). +## Prowler App + + + +### Step 1: Access Prowler Cloud/App + +1. Navigate to [Prowler Cloud](https://cloud.prowler.com/) or launch [Prowler App](/user-guide/tutorials/prowler-app) +2. Go to "Configuration" > "Cloud Providers" + + ![Cloud Providers Page](/images/prowler-app/cloud-providers-page.png) + +3. Click "Add Cloud Provider" + + ![Add a Cloud Provider](/images/prowler-app/add-cloud-provider.png) + +4. Select "Infrastructure as Code" + + ![Select Infrastructure as Code](/images/providers/select-iac.png) + +5. Add the Repository URL and an optional alias, then click "Next" + + ![Add IaC Repository URL](/images/providers/add-iac-repo.png) + +### Step 2: Enter Authentication Details + +6. Optionally provide the [authentication](/user-guide/providers/iac/authentication) details for private repositories, then click "Next" + + ![IaC Authentication](/images/providers/iac-authentication.png) + +### Step 3: Verify Connection & Start Scan + +7. Review the provider configuration and click "Launch scan" to initiate the scan + + ![Verify Connection & Start Scan](/images/providers/iac-verify-connection.png) + + ## Prowler CLI + + ### Usage Use the `iac` argument to run Prowler with the IaC provider. Specify the directory or repository to scan, frameworks to include, and paths to exclude. diff --git a/poetry.lock b/poetry.lock index 847a31f878..12bc3ea2de 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand. [[package]] name = "about-time" @@ -4420,106 +4420,127 @@ typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regex" -version = "2024.11.6" +version = "2025.9.18" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.8" -groups = ["dev"] +python-versions = ">=3.9" +groups = ["dev", "docs"] files = [ - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, - {file = "regex-2024.11.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c"}, - {file = "regex-2024.11.6-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008"}, - {file = "regex-2024.11.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62"}, - {file = "regex-2024.11.6-cp310-cp310-win32.whl", hash = "sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e"}, - {file = "regex-2024.11.6-cp310-cp310-win_amd64.whl", hash = "sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7"}, - {file = "regex-2024.11.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0"}, - {file = "regex-2024.11.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d"}, - {file = "regex-2024.11.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45"}, - {file = "regex-2024.11.6-cp311-cp311-win32.whl", hash = "sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9"}, - {file = "regex-2024.11.6-cp311-cp311-win_amd64.whl", hash = "sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9"}, - {file = "regex-2024.11.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e"}, - {file = "regex-2024.11.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51"}, - {file = "regex-2024.11.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad"}, - {file = "regex-2024.11.6-cp312-cp312-win32.whl", hash = "sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54"}, - {file = "regex-2024.11.6-cp312-cp312-win_amd64.whl", hash = "sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4"}, - {file = "regex-2024.11.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c"}, - {file = "regex-2024.11.6-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4"}, - {file = "regex-2024.11.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d"}, - {file = "regex-2024.11.6-cp313-cp313-win32.whl", hash = "sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff"}, - {file = "regex-2024.11.6-cp313-cp313-win_amd64.whl", hash = "sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3"}, - {file = "regex-2024.11.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f"}, - {file = "regex-2024.11.6-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc"}, - {file = "regex-2024.11.6-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f"}, - {file = "regex-2024.11.6-cp38-cp38-win32.whl", hash = "sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4"}, - {file = "regex-2024.11.6-cp38-cp38-win_amd64.whl", hash = "sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e"}, - {file = "regex-2024.11.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48"}, - {file = "regex-2024.11.6-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f"}, - {file = "regex-2024.11.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b"}, - {file = "regex-2024.11.6-cp39-cp39-win32.whl", hash = "sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57"}, - {file = "regex-2024.11.6-cp39-cp39-win_amd64.whl", hash = "sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983"}, - {file = "regex-2024.11.6.tar.gz", hash = "sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519"}, + {file = "regex-2025.9.18-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:12296202480c201c98a84aecc4d210592b2f55e200a1d193235c4db92b9f6788"}, + {file = "regex-2025.9.18-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:220381f1464a581f2ea988f2220cf2a67927adcef107d47d6897ba5a2f6d51a4"}, + {file = "regex-2025.9.18-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:87f681bfca84ebd265278b5daa1dcb57f4db315da3b5d044add7c30c10442e61"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:34d674cbba70c9398074c8a1fcc1a79739d65d1105de2a3c695e2b05ea728251"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:385c9b769655cb65ea40b6eea6ff763cbb6d69b3ffef0b0db8208e1833d4e746"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8900b3208e022570ae34328712bef6696de0804c122933414014bae791437ab2"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c204e93bf32cd7a77151d44b05eb36f469d0898e3fba141c026a26b79d9914a0"}, + {file = "regex-2025.9.18-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3acc471d1dd7e5ff82e6cacb3b286750decd949ecd4ae258696d04f019817ef8"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6479d5555122433728760e5f29edb4c2b79655a8deb681a141beb5c8a025baea"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:431bd2a8726b000eb6f12429c9b438a24062a535d06783a93d2bcbad3698f8a8"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0cc3521060162d02bd36927e20690129200e5ac9d2c6d32b70368870b122db25"}, + {file = "regex-2025.9.18-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a021217b01be2d51632ce056d7a837d3fa37c543ede36e39d14063176a26ae29"}, + {file = "regex-2025.9.18-cp310-cp310-win32.whl", hash = "sha256:4a12a06c268a629cb67cc1d009b7bb0be43e289d00d5111f86a2efd3b1949444"}, + {file = "regex-2025.9.18-cp310-cp310-win_amd64.whl", hash = "sha256:47acd811589301298c49db2c56bde4f9308d6396da92daf99cba781fa74aa450"}, + {file = "regex-2025.9.18-cp310-cp310-win_arm64.whl", hash = "sha256:16bd2944e77522275e5ee36f867e19995bcaa533dcb516753a26726ac7285442"}, + {file = "regex-2025.9.18-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:51076980cd08cd13c88eb7365427ae27f0d94e7cebe9ceb2bb9ffdae8fc4d82a"}, + {file = "regex-2025.9.18-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:828446870bd7dee4e0cbeed767f07961aa07f0ea3129f38b3ccecebc9742e0b8"}, + {file = "regex-2025.9.18-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c28821d5637866479ec4cc23b8c990f5bc6dd24e5e4384ba4a11d38a526e1414"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:726177ade8e481db669e76bf99de0b278783be8acd11cef71165327abd1f170a"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f5cca697da89b9f8ea44115ce3130f6c54c22f541943ac8e9900461edc2b8bd4"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dfbde38f38004703c35666a1e1c088b778e35d55348da2b7b278914491698d6a"}, + {file = "regex-2025.9.18-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f2f422214a03fab16bfa495cfec72bee4aaa5731843b771860a471282f1bf74f"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a295916890f4df0902e4286bc7223ee7f9e925daa6dcdec4192364255b70561a"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:5db95ff632dbabc8c38c4e82bf545ab78d902e81160e6e455598014f0abe66b9"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fb967eb441b0f15ae610b7069bdb760b929f267efbf522e814bbbfffdf125ce2"}, + {file = "regex-2025.9.18-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f04d2f20da4053d96c08f7fde6e1419b7ec9dbcee89c96e3d731fca77f411b95"}, + {file = "regex-2025.9.18-cp311-cp311-win32.whl", hash = "sha256:895197241fccf18c0cea7550c80e75f185b8bd55b6924fcae269a1a92c614a07"}, + {file = "regex-2025.9.18-cp311-cp311-win_amd64.whl", hash = "sha256:7e2b414deae99166e22c005e154a5513ac31493db178d8aec92b3269c9cce8c9"}, + {file = "regex-2025.9.18-cp311-cp311-win_arm64.whl", hash = "sha256:fb137ec7c5c54f34a25ff9b31f6b7b0c2757be80176435bf367111e3f71d72df"}, + {file = "regex-2025.9.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:436e1b31d7efd4dcd52091d076482031c611dde58bf9c46ca6d0a26e33053a7e"}, + {file = "regex-2025.9.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c190af81e5576b9c5fdc708f781a52ff20f8b96386c6e2e0557a78402b029f4a"}, + {file = "regex-2025.9.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e4121f1ce2b2b5eec4b397cc1b277686e577e658d8f5870b7eb2d726bd2300ab"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:300e25dbbf8299d87205e821a201057f2ef9aa3deb29caa01cd2cac669e508d5"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7b47fcf9f5316c0bdaf449e879407e1b9937a23c3b369135ca94ebc8d74b1742"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:57a161bd3acaa4b513220b49949b07e252165e6b6dc910ee7617a37ff4f5b425"}, + {file = "regex-2025.9.18-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f130c3a7845ba42de42f380fff3c8aebe89a810747d91bcf56d40a069f15352"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5f96fa342b6f54dcba928dd452e8d8cb9f0d63e711d1721cd765bb9f73bb048d"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f0d676522d68c207828dcd01fb6f214f63f238c283d9f01d85fc664c7c85b56"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:40532bff8a1a0621e7903ae57fce88feb2e8a9a9116d341701302c9302aef06e"}, + {file = "regex-2025.9.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:039f11b618ce8d71a1c364fdee37da1012f5a3e79b1b2819a9f389cd82fd6282"}, + {file = "regex-2025.9.18-cp312-cp312-win32.whl", hash = "sha256:e1dd06f981eb226edf87c55d523131ade7285137fbde837c34dc9d1bf309f459"}, + {file = "regex-2025.9.18-cp312-cp312-win_amd64.whl", hash = "sha256:3d86b5247bf25fa3715e385aa9ff272c307e0636ce0c9595f64568b41f0a9c77"}, + {file = "regex-2025.9.18-cp312-cp312-win_arm64.whl", hash = "sha256:032720248cbeeae6444c269b78cb15664458b7bb9ed02401d3da59fe4d68c3a5"}, + {file = "regex-2025.9.18-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2a40f929cd907c7e8ac7566ac76225a77701a6221bca937bdb70d56cb61f57b2"}, + {file = "regex-2025.9.18-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c90471671c2cdf914e58b6af62420ea9ecd06d1554d7474d50133ff26ae88feb"}, + {file = "regex-2025.9.18-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:1a351aff9e07a2dabb5022ead6380cff17a4f10e4feb15f9100ee56c4d6d06af"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bc4b8e9d16e20ddfe16430c23468a8707ccad3365b06d4536142e71823f3ca29"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4b8cdbddf2db1c5e80338ba2daa3cfa3dec73a46fff2a7dda087c8efbf12d62f"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a276937d9d75085b2c91fb48244349c6954f05ee97bba0963ce24a9d915b8b68"}, + {file = "regex-2025.9.18-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92a8e375ccdc1256401c90e9dc02b8642894443d549ff5e25e36d7cf8a80c783"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0dc6893b1f502d73037cf807a321cdc9be29ef3d6219f7970f842475873712ac"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a61e85bfc63d232ac14b015af1261f826260c8deb19401c0597dbb87a864361e"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1ef86a9ebc53f379d921fb9a7e42b92059ad3ee800fcd9e0fe6181090e9f6c23"}, + {file = "regex-2025.9.18-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d3bc882119764ba3a119fbf2bd4f1b47bc56c1da5d42df4ed54ae1e8e66fdf8f"}, + {file = "regex-2025.9.18-cp313-cp313-win32.whl", hash = "sha256:3810a65675845c3bdfa58c3c7d88624356dd6ee2fc186628295e0969005f928d"}, + {file = "regex-2025.9.18-cp313-cp313-win_amd64.whl", hash = "sha256:16eaf74b3c4180ede88f620f299e474913ab6924d5c4b89b3833bc2345d83b3d"}, + {file = "regex-2025.9.18-cp313-cp313-win_arm64.whl", hash = "sha256:4dc98ba7dd66bd1261927a9f49bd5ee2bcb3660f7962f1ec02617280fc00f5eb"}, + {file = "regex-2025.9.18-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:fe5d50572bc885a0a799410a717c42b1a6b50e2f45872e2b40f4f288f9bce8a2"}, + {file = "regex-2025.9.18-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:1b9d9a2d6cda6621551ca8cf7a06f103adf72831153f3c0d982386110870c4d3"}, + {file = "regex-2025.9.18-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:13202e4c4ac0ef9a317fff817674b293c8f7e8c68d3190377d8d8b749f566e12"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:874ff523b0fecffb090f80ae53dc93538f8db954c8bb5505f05b7787ab3402a0"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d13ab0490128f2bb45d596f754148cd750411afc97e813e4b3a61cf278a23bb6"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05440bc172bc4b4b37fb9667e796597419404dbba62e171e1f826d7d2a9ebcef"}, + {file = "regex-2025.9.18-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5514b8e4031fdfaa3d27e92c75719cbe7f379e28cacd939807289bce76d0e35a"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:65d3c38c39efce73e0d9dc019697b39903ba25b1ad45ebbd730d2cf32741f40d"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ae77e447ebc144d5a26d50055c6ddba1d6ad4a865a560ec7200b8b06bc529368"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e3ef8cf53dc8df49d7e28a356cf824e3623764e9833348b655cfed4524ab8a90"}, + {file = "regex-2025.9.18-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9feb29817df349c976da9a0debf775c5c33fc1c8ad7b9f025825da99374770b7"}, + {file = "regex-2025.9.18-cp313-cp313t-win32.whl", hash = "sha256:168be0d2f9b9d13076940b1ed774f98595b4e3c7fc54584bba81b3cc4181742e"}, + {file = "regex-2025.9.18-cp313-cp313t-win_amd64.whl", hash = "sha256:d59ecf3bb549e491c8104fea7313f3563c7b048e01287db0a90485734a70a730"}, + {file = "regex-2025.9.18-cp313-cp313t-win_arm64.whl", hash = "sha256:dbef80defe9fb21310948a2595420b36c6d641d9bea4c991175829b2cc4bc06a"}, + {file = "regex-2025.9.18-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:c6db75b51acf277997f3adcd0ad89045d856190d13359f15ab5dda21581d9129"}, + {file = "regex-2025.9.18-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8f9698b6f6895d6db810e0bda5364f9ceb9e5b11328700a90cae573574f61eea"}, + {file = "regex-2025.9.18-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:29cd86aa7cb13a37d0f0d7c21d8d949fe402ffa0ea697e635afedd97ab4b69f1"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7c9f285a071ee55cd9583ba24dde006e53e17780bb309baa8e4289cd472bcc47"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5adf266f730431e3be9021d3e5b8d5ee65e563fec2883ea8093944d21863b379"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1137cabc0f38807de79e28d3f6e3e3f2cc8cfb26bead754d02e6d1de5f679203"}, + {file = "regex-2025.9.18-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7cc9e5525cada99699ca9223cce2d52e88c52a3d2a0e842bd53de5497c604164"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:bbb9246568f72dce29bcd433517c2be22c7791784b223a810225af3b50d1aafb"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:6a52219a93dd3d92c675383efff6ae18c982e2d7651c792b1e6d121055808743"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:ae9b3840c5bd456780e3ddf2f737ab55a79b790f6409182012718a35c6d43282"}, + {file = "regex-2025.9.18-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d488c236ac497c46a5ac2005a952c1a0e22a07be9f10c3e735bc7d1209a34773"}, + {file = "regex-2025.9.18-cp314-cp314-win32.whl", hash = "sha256:0c3506682ea19beefe627a38872d8da65cc01ffa25ed3f2e422dffa1474f0788"}, + {file = "regex-2025.9.18-cp314-cp314-win_amd64.whl", hash = "sha256:57929d0f92bebb2d1a83af372cd0ffba2263f13f376e19b1e4fa32aec4efddc3"}, + {file = "regex-2025.9.18-cp314-cp314-win_arm64.whl", hash = "sha256:6a4b44df31d34fa51aa5c995d3aa3c999cec4d69b9bd414a8be51984d859f06d"}, + {file = "regex-2025.9.18-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:b176326bcd544b5e9b17d6943f807697c0cb7351f6cfb45bf5637c95ff7e6306"}, + {file = "regex-2025.9.18-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0ffd9e230b826b15b369391bec167baed57c7ce39efc35835448618860995946"}, + {file = "regex-2025.9.18-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:ec46332c41add73f2b57e2f5b642f991f6b15e50e9f86285e08ffe3a512ac39f"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b80fa342ed1ea095168a3f116637bd1030d39c9ff38dc04e54ef7c521e01fc95"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f4d97071c0ba40f0cf2a93ed76e660654c399a0a04ab7d85472239460f3da84b"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:0ac936537ad87cef9e0e66c5144484206c1354224ee811ab1519a32373e411f3"}, + {file = "regex-2025.9.18-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dec57f96d4def58c422d212d414efe28218d58537b5445cf0c33afb1b4768571"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:48317233294648bf7cd068857f248e3a57222259a5304d32c7552e2284a1b2ad"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:274687e62ea3cf54846a9b25fc48a04459de50af30a7bd0b61a9e38015983494"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:a78722c86a3e7e6aadf9579e3b0ad78d955f2d1f1a8ca4f67d7ca258e8719d4b"}, + {file = "regex-2025.9.18-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:06104cd203cdef3ade989a1c45b6215bf42f8b9dd705ecc220c173233f7cba41"}, + {file = "regex-2025.9.18-cp314-cp314t-win32.whl", hash = "sha256:2e1eddc06eeaffd249c0adb6fafc19e2118e6308c60df9db27919e96b5656096"}, + {file = "regex-2025.9.18-cp314-cp314t-win_amd64.whl", hash = "sha256:8620d247fb8c0683ade51217b459cb4a1081c0405a3072235ba43a40d355c09a"}, + {file = "regex-2025.9.18-cp314-cp314t-win_arm64.whl", hash = "sha256:b7531a8ef61de2c647cdf68b3229b071e46ec326b3138b2180acb4275f470b01"}, + {file = "regex-2025.9.18-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3dbcfcaa18e9480669030d07371713c10b4f1a41f791ffa5cb1a99f24e777f40"}, + {file = "regex-2025.9.18-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1e85f73ef7095f0380208269055ae20524bfde3f27c5384126ddccf20382a638"}, + {file = "regex-2025.9.18-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9098e29b3ea4ffffeade423f6779665e2a4f8db64e699c0ed737ef0db6ba7b12"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90b6b7a2d0f45b7ecaaee1aec6b362184d6596ba2092dd583ffba1b78dd0231c"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c81b892af4a38286101502eae7aec69f7cd749a893d9987a92776954f3943408"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3b524d010973f2e1929aeb635418d468d869a5f77b52084d9f74c272189c251d"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b498437c026a3d5d0be0020023ff76d70ae4d77118e92f6f26c9d0423452446"}, + {file = "regex-2025.9.18-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0716e4d6e58853d83f6563f3cf25c281ff46cf7107e5f11879e32cb0b59797d9"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:065b6956749379d41db2625f880b637d4acc14c0a4de0d25d609a62850e96d36"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d4a691494439287c08ddb9b5793da605ee80299dd31e95fa3f323fac3c33d9d4"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ef8d10cc0989565bcbe45fb4439f044594d5c2b8919d3d229ea2c4238f1d55b0"}, + {file = "regex-2025.9.18-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4baeb1b16735ac969a7eeecc216f1f8b7caf60431f38a2671ae601f716a32d25"}, + {file = "regex-2025.9.18-cp39-cp39-win32.whl", hash = "sha256:8e5f41ad24a1e0b5dfcf4c4e5d9f5bd54c895feb5708dd0c1d0d35693b24d478"}, + {file = "regex-2025.9.18-cp39-cp39-win_amd64.whl", hash = "sha256:50e8290707f2fb8e314ab3831e594da71e062f1d623b05266f8cfe4db4949afd"}, + {file = "regex-2025.9.18-cp39-cp39-win_arm64.whl", hash = "sha256:039a9d7195fd88c943d7c777d4941e8ef736731947becce773c31a1009cb3c35"}, + {file = "regex-2025.9.18.tar.gz", hash = "sha256:c5ba23274c61c6fef447ba6a39333297d0c247f53059dba0bca415cac511edc4"}, ] [[package]] diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 7f3f8b946f..eb33889546 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -13,6 +13,12 @@ All notable changes to the **Prowler SDK** are documented in this file. - `cloudstorage_bucket_logging_enabled` check for GCP provider [(#9091)](https://github.com/prowler-cloud/prowler/pull/9091) - C5 compliance framework for Azure provider [(#9081)](https://github.com/prowler-cloud/prowler/pull/9081) - C5 compliance framework for the GCP provider [(#9097)](https://github.com/prowler-cloud/prowler/pull/9097) +- `organization_repository_creation_limited` check for GitHub provider [(#8844)](https://github.com/prowler-cloud/prowler/pull/8844) +- HIPAA compliance framework for the GCP provider [(#8955)](https://github.com/prowler-cloud/prowler/pull/8955) +- Add organization ID parameter for MongoDB Atlas provider [(#9167)](https://github.com/prowler-cloud/prowler/pull/9167) +- Add multiple compliance improvements [(#9145)](https://github.com/prowler-cloud/prowler/pull/9145) +- Added validation for invalid checks, services, and categories in `load_checks_to_execute` function [(#8971)](https://github.com/prowler-cloud/prowler/pull/8971) +- NIST CSF 2.0 compliance framework for the AWS provider [(#9185)](https://github.com/prowler-cloud/prowler/pull/9185) ### Changed - Update AWS Direct Connect service metadata to new format [(#8855)](https://github.com/prowler-cloud/prowler/pull/8855) @@ -31,17 +37,33 @@ All notable changes to the **Prowler SDK** are documented in this file. - Update AWS FMS service metadata to new format [(#9005)](https://github.com/prowler-cloud/prowler/pull/9005) - Update AWS FSx service metadata to new format [(#9006)](https://github.com/prowler-cloud/prowler/pull/9006) - Update AWS Glacier service metadata to new format [(#9007)](https://github.com/prowler-cloud/prowler/pull/9007) +- Update oraclecloud analytics service metadata to new format [(#9114)](https://github.com/prowler-cloud/prowler/pull/9114) + - Update AWS CodeArtifact service metadata to new format [(#8850)](https://github.com/prowler-cloud/prowler/pull/8850) +- Rename OCI provider to oraclecloud with oci alias [(#9126)](https://github.com/prowler-cloud/prowler/pull/9126) --- -## [v5.13.1] (Prowler UNRELEASED) +## [v5.13.2] (Prowler UNRELEASED) + +### Fixed +- Check `check_name` has no `resource_name` error for GCP provider [(#9169)](https://github.com/prowler-cloud/prowler/pull/9169) + +--- + +## [v5.13.1] (Prowler v5.13.1) ### Fixed - Add `resource_name` for checks under `logging` for the GCP provider [(#9023)](https://github.com/prowler-cloud/prowler/pull/9023) - Fix `ec2_instance_with_outdated_ami` check to handle None AMIs [(#9046)](https://github.com/prowler-cloud/prowler/pull/9046) - Handle timestamp when transforming compliance findings in CCC [(#9042)](https://github.com/prowler-cloud/prowler/pull/9042) - Update `resource_id` for admincenter service and avoid unnecessary msgraph requests [(#9019)](https://github.com/prowler-cloud/prowler/pull/9019) +- Fix `firehose_stream_encrypted_at_rest` description and findings clarity [(#9142)](https://github.com/prowler-cloud/prowler/pull/9142) + +--- + +### Changed +- Adapt IaC provider to be used in the Prowler App [(#8751)](https://github.com/prowler-cloud/prowler/pull/8751) --- diff --git a/prowler/__main__.py b/prowler/__main__.py index 10a4ad7e21..2227c6c645 100644 --- a/prowler/__main__.py +++ b/prowler/__main__.py @@ -61,7 +61,7 @@ from prowler.lib.outputs.compliance.cis.cis_gcp import GCPCIS from prowler.lib.outputs.compliance.cis.cis_github import GithubCIS from prowler.lib.outputs.compliance.cis.cis_kubernetes import KubernetesCIS from prowler.lib.outputs.compliance.cis.cis_m365 import M365CIS -from prowler.lib.outputs.compliance.cis.cis_oci import OCICIS +from prowler.lib.outputs.compliance.cis.cis_oraclecloud import OracleCloudCIS from prowler.lib.outputs.compliance.compliance import display_compliance_table from prowler.lib.outputs.compliance.ens.ens_aws import AWSENS from prowler.lib.outputs.compliance.ens.ens_azure import AzureENS @@ -334,7 +334,7 @@ def prowler(): output_options = IACOutputOptions(args, bulk_checks_metadata) elif provider == "llm": output_options = LLMOutputOptions(args, bulk_checks_metadata) - elif provider == "oci": + elif provider == "oraclecloud": output_options = OCIOutputOptions( args, bulk_checks_metadata, global_provider.identity ) @@ -359,6 +359,12 @@ def prowler(): else: # Original behavior for IAC or non-verbose LLM findings = global_provider.run() + # Note: IaC doesn't support granular progress tracking since Trivy runs as a black box + # and returns all findings at once. Progress tracking would just be 0% → 100%. + + # Filter findings by status if specified + if hasattr(args, "status") and args.status: + findings = [f for f in findings if f.status in args.status] # Report findings for verbose output report(findings, global_provider, output_options) elif len(checks_to_execute): @@ -963,7 +969,7 @@ def prowler(): generated_outputs["compliance"].append(generic_compliance) generic_compliance.batch_write_data_to_file() - elif provider == "oci": + elif provider == "oraclecloud": for compliance_name in input_compliance_frameworks: if compliance_name.startswith("cis_"): # Generate CIS Finding Object @@ -971,7 +977,7 @@ def prowler(): f"{output_options.output_directory}/compliance/" f"{output_options.output_filename}_{compliance_name}.csv" ) - cis = OCICIS( + cis = OracleCloudCIS( findings=finding_outputs, compliance=bulk_compliance_frameworks[compliance_name], file_path=filename, diff --git a/prowler/compliance/aws/ens_rd2022_aws.json b/prowler/compliance/aws/ens_rd2022_aws.json index 5d713c2d1d..1d25aeb3b3 100644 --- a/prowler/compliance/aws/ens_rd2022_aws.json +++ b/prowler/compliance/aws/ens_rd2022_aws.json @@ -1,6 +1,6 @@ { "Framework": "ENS", - "Name": "ENS RD 311/2022", + "Name": "ENS RD 311/2022 - Categoría Alta", "Version": "RD2022", "Provider": "AWS", "Description": "The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", diff --git a/prowler/compliance/aws/nis2_aws.json b/prowler/compliance/aws/nis2_aws.json index c9dcb37390..dc6b75657f 100644 --- a/prowler/compliance/aws/nis2_aws.json +++ b/prowler/compliance/aws/nis2_aws.json @@ -1,6 +1,6 @@ { "Framework": "NIS2", - "Name": "Network and Information Security Directive (Directive (EU) 2022/2555)", + "Name": "NIS2 - Network and Information Security Directive (Directive (EU) 2022/2555)", "Version": "", "Provider": "AWS", "Description": "ANNEX to the Commission Implementing Regulation laying down rules for the application of Directive (EU) 2022/2555 as regards technical and methodological requirements of cybersecurity risk-management measures and further specification of the cases in which an incident is considered to be significant with regard to DNS service providers, TLD name registries, cloud computing service providers, data centre service providers, content delivery network providers, managed service providers, managed security service providers, providers of online market places, of online search engines and of social networking services platforms, and trust service providers", diff --git a/prowler/compliance/aws/nist_csf_2.0_aws.json b/prowler/compliance/aws/nist_csf_2.0_aws.json new file mode 100644 index 0000000000..3430763879 --- /dev/null +++ b/prowler/compliance/aws/nist_csf_2.0_aws.json @@ -0,0 +1,1612 @@ +{ + "Framework": "NIST-CSF", + "Name": "National Institute of Standards and Technology (NIST) Cybersecurity Framework (CSF) v2.0", + "Version": "2.0", + "Provider": "AWS", + "Description": "The NIST Cybersecurity Framework (CSF) 2.0 offers a taxonomy of high-level cybersecurity outcomes that can be used by any organization regardless of its size, sector, or maturity to better understand, assess, prioritize, and communicate its cybersecurity efforts. The framework's core functions are organized into six key areas: Govern (new), Identify, Protect, Detect, Respond, and Recover. Together, these functions provide a comprehensive lifecycle approach to managing cybersecurity risk.", + "Requirements": [ + { + "Id": "oc_1", + "Name": "GV.OC-1", + "Description": "The organization's role in the supply chain is identified and communicated.", + "Attributes": [ + { + "ItemId": "oc_1", + "Section": "Govern (GV)", + "SubSection": "Organizational Context (GV.OC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "oc_2", + "Name": "GV.OC-2", + "Description": "Legal, regulatory, and contractual requirements regarding cybersecurity — including privacy and civil liberties obligations — are understood and managed.", + "Attributes": [ + { + "ItemId": "oc_2", + "Section": "Govern (GV)", + "SubSection": "Organizational Context (GV.OC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "oc_3", + "Name": "GV.OC-3", + "Description": "The organization's place in critical infrastructure and its industry sector is identified and communicated.", + "Attributes": [ + { + "ItemId": "oc_3", + "Section": "Govern (GV)", + "SubSection": "Organizational Context (GV.OC)", + "Service": "aws" + } + ], + "Checks": [ + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "rm_1", + "Name": "GV.RM-1", + "Description": "Organizational cybersecurity risk management strategy is established, communicated, and maintained.", + "Attributes": [ + { + "ItemId": "rm_1", + "Section": "Govern (GV)", + "SubSection": "Risk Management Strategy (GV.RM)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "rm_2", + "Name": "GV.RM-2", + "Description": "Organizational risk tolerance is determined and clearly expressed.", + "Attributes": [ + { + "ItemId": "rm_2", + "Section": "Govern (GV)", + "SubSection": "Risk Management Strategy (GV.RM)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "rm_3", + "Name": "GV.RM-3", + "Description": "The organization's determination of risk tolerance is informed by its role in critical infrastructure, sector-specific risk analysis, or organizational risk analysis.", + "Attributes": [ + { + "ItemId": "rm_3", + "Section": "Govern (GV)", + "SubSection": "Risk Management Strategy (GV.RM)", + "Service": "aws" + } + ], + "Checks": [ + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "sc_1", + "Name": "GV.SC-1", + "Description": "Cybersecurity supply chain risk management processes are identified, established, assessed, managed, and agreed to by organizational stakeholders.", + "Attributes": [ + { + "ItemId": "sc_1", + "Section": "Govern (GV)", + "SubSection": "Cybersecurity Supply Chain Risk Management (GV.SC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "sc_2", + "Name": "GV.SC-2", + "Description": "Supply chain risk management processes are established, managed, and agreed to by organizational stakeholders.", + "Attributes": [ + { + "ItemId": "sc_2", + "Section": "Govern (GV)", + "SubSection": "Cybersecurity Supply Chain Risk Management (GV.SC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "sc_3", + "Name": "GV.SC-3", + "Description": "Suppliers and third-party partners are evaluated, assessed, and monitored using cybersecurity supply chain risk management processes.", + "Attributes": [ + { + "ItemId": "sc_3", + "Section": "Govern (GV)", + "SubSection": "Cybersecurity Supply Chain Risk Management (GV.SC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "sc_4", + "Name": "GV.SC-4", + "Description": "Supply chain risk management processes are continuously improved.", + "Attributes": [ + { + "ItemId": "sc_4", + "Section": "Govern (GV)", + "SubSection": "Cybersecurity Supply Chain Risk Management (GV.SC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "rr_1", + "Name": "GV.RR-1", + "Description": "Cybersecurity roles and responsibilities are coordinated and aligned with internal roles and external partners.", + "Attributes": [ + { + "ItemId": "rr_1", + "Section": "Govern (GV)", + "SubSection": "Roles, Responsibilities, and Authorities (GV.RR)", + "Service": "iam" + } + ], + "Checks": [ + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges", + "iam_inline_policy_no_administrative_privileges", + "iam_no_root_access_key", + "cloudtrail_multi_region_enabled" + ] + }, + { + "Id": "rr_2", + "Name": "GV.RR-2", + "Description": "Cybersecurity responsibilities are established and communicated.", + "Attributes": [ + { + "ItemId": "rr_2", + "Section": "Govern (GV)", + "SubSection": "Roles, Responsibilities, and Authorities (GV.RR)", + "Service": "iam" + } + ], + "Checks": [ + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges", + "iam_inline_policy_no_administrative_privileges", + "cloudtrail_multi_region_enabled" + ] + }, + { + "Id": "rr_3", + "Name": "GV.RR-3", + "Description": "Senior executives are accountable for cybersecurity risk.", + "Attributes": [ + { + "ItemId": "rr_3", + "Section": "Govern (GV)", + "SubSection": "Roles, Responsibilities, and Authorities (GV.RR)", + "Service": "aws" + } + ], + "Checks": [ + "iam_root_hardware_mfa_enabled", + "iam_root_mfa_enabled", + "iam_no_root_access_key", + "cloudtrail_multi_region_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "po_1", + "Name": "GV.PO-1", + "Description": "Cybersecurity policy is established, communicated, and enforced.", + "Attributes": [ + { + "ItemId": "po_1", + "Section": "Govern (GV)", + "SubSection": "Policies, Processes, and Procedures (GV.PO)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "iam_password_policy_reuse_24", + "securityhub_enabled" + ] + }, + { + "Id": "po_2", + "Name": "GV.PO-2", + "Description": "Cybersecurity policy is updated as needed to reflect changes in organizational priorities, threat landscape, or technology.", + "Attributes": [ + { + "ItemId": "po_2", + "Section": "Govern (GV)", + "SubSection": "Policies, Processes, and Procedures (GV.PO)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "config_recorder_all_regions_enabled", + "cloudwatch_log_metric_filter_policy_changes" + ] + }, + { + "Id": "po_3", + "Name": "GV.PO-3", + "Description": "Legal and regulatory requirements regarding cybersecurity, including privacy and civil liberties obligations, are understood and managed.", + "Attributes": [ + { + "ItemId": "po_3", + "Section": "Govern (GV)", + "SubSection": "Policies, Processes, and Procedures (GV.PO)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "po_4", + "Name": "GV.PO-4", + "Description": "Governance and risk management processes address cybersecurity risks.", + "Attributes": [ + { + "ItemId": "po_4", + "Section": "Govern (GV)", + "SubSection": "Policies, Processes, and Procedures (GV.PO)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "po_5", + "Name": "GV.PO-5", + "Description": "Processes for managing cybersecurity requirements for suppliers and third-party partners are established.", + "Attributes": [ + { + "ItemId": "po_5", + "Section": "Govern (GV)", + "SubSection": "Policies, Processes, and Procedures (GV.PO)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ov_1", + "Name": "GV.OV-1", + "Description": "Cybersecurity risk management strategy outcomes are reviewed to inform and adjust organizational priorities.", + "Attributes": [ + { + "ItemId": "ov_1", + "Section": "Govern (GV)", + "SubSection": "Oversight (GV.OV)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ov_2", + "Name": "GV.OV-2", + "Description": "Cybersecurity risk management performance is measured and reported.", + "Attributes": [ + { + "ItemId": "ov_2", + "Section": "Govern (GV)", + "SubSection": "Oversight (GV.OV)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ov_3", + "Name": "GV.OV-3", + "Description": "Cybersecurity risk management strategy and practices are reviewed and adjusted to adapt to changes in the threat landscape, technologies, or mission, business, or system environments.", + "Attributes": [ + { + "ItemId": "ov_3", + "Section": "Govern (GV)", + "SubSection": "Oversight (GV.OV)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "config_recorder_all_regions_enabled", + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ov_4", + "Name": "GV.OV-4", + "Description": "Cybersecurity risk management processes are reviewed to ensure they meet legal and regulatory requirements.", + "Attributes": [ + { + "ItemId": "ov_4", + "Section": "Govern (GV)", + "SubSection": "Oversight (GV.OV)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "config_recorder_all_regions_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "am_1", + "Name": "ID.AM-1", + "Description": "Physical devices and systems within the organization are inventoried.", + "Attributes": [ + { + "ItemId": "am_1", + "Section": "Identify (ID)", + "SubSection": "Asset Management (ID.AM)", + "Service": "aws" + } + ], + "Checks": [ + "config_recorder_all_regions_enabled", + "ec2_instance_managed_by_ssm" + ] + }, + { + "Id": "am_2", + "Name": "ID.AM-2", + "Description": "Software platforms and applications within the organization are inventoried.", + "Attributes": [ + { + "ItemId": "am_2", + "Section": "Identify (ID)", + "SubSection": "Asset Management (ID.AM)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_instance_managed_by_ssm", + "ssm_managed_compliant_patching" + ] + }, + { + "Id": "am_3", + "Name": "ID.AM-3", + "Description": "Organizational communication and data flows are mapped.", + "Attributes": [ + { + "ItemId": "am_3", + "Section": "Identify (ID)", + "SubSection": "Asset Management (ID.AM)", + "Service": "aws" + } + ], + "Checks": [ + "apigateway_restapi_logging_enabled", + "cloudtrail_multi_region_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "redshift_cluster_audit_logging", + "s3_bucket_server_access_logging_enabled", + "vpc_flow_logs_enabled" + ] + }, + { + "Id": "am_5", + "Name": "ID.AM-5", + "Description": "Resources (e.g., hardware, devices, data, time, personnel, and software) are prioritized based on their classification, criticality, and business value.", + "Attributes": [ + { + "ItemId": "am_5", + "Section": "Identify (ID)", + "SubSection": "Asset Management (ID.AM)", + "Service": "aws" + } + ], + "Checks": [] + }, + { + "Id": "am_6", + "Name": "ID.AM-6", + "Description": "Cybersecurity roles and responsibilities for the entire workforce and third-party stakeholders (e.g., suppliers, customers, partners) are established.", + "Attributes": [ + { + "ItemId": "am_6", + "Section": "Identify (ID)", + "SubSection": "Asset Management (ID.AM)", + "Service": "iam" + } + ], + "Checks": [] + }, + { + "Id": "be_5", + "Name": "ID.BE-5", + "Description": "Resilience requirements to support delivery of critical services are established for all operating states (e.g. under duress/attack, during recovery, normal operations)", + "Attributes": [ + { + "ItemId": "be_5", + "Section": "Identify (ID)", + "SubSection": "Business Environment (ID.BE)", + "Service": "aws" + } + ], + "Checks": [ + "elbv2_deletion_protection", + "rds_instance_backup_enabled", + "rds_instance_multi_az", + "s3_bucket_object_versioning" + ] + }, + { + "Id": "ra_1", + "Name": "ID.RA-1", + "Description": "Asset vulnerabilities are identified and documented.", + "Attributes": [ + { + "ItemId": "ra_1", + "Section": "Identify (ID)", + "SubSection": "Risk Assessment (ID.RA)", + "Service": "aws" + } + ], + "Checks": [ + "guardduty_is_enabled", + "securityhub_enabled", + "ssm_managed_compliant_patching" + ] + }, + { + "Id": "ra_2", + "Name": "ID.RA-2", + "Description": "Cyber threat intelligence is received from information sharing forums and sources.", + "Attributes": [ + { + "ItemId": "ra_2", + "Section": "Identify (ID)", + "SubSection": "Risk Assessment (ID.RA)", + "Service": "aws" + } + ], + "Checks": [ + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ra_3", + "Name": "ID.RA-3", + "Description": "Threats, both internal and external, are identified and documented.", + "Attributes": [ + { + "ItemId": "ra_3", + "Section": "Identify (ID)", + "SubSection": "Risk Assessment (ID.RA)", + "Service": "aws" + } + ], + "Checks": [ + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ra_5", + "Name": "ID.RA-5", + "Description": "Threats, vulnerabilities, likelihoods, and impacts are used to determine risk.", + "Attributes": [ + { + "ItemId": "ra_5", + "Section": "Identify (ID)", + "SubSection": "Risk Assessment (ID.RA)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_cloudwatch_logging_enabled", + "cloudwatch_changes_to_network_acls_alarm_configured", + "cloudwatch_changes_to_network_gateways_alarm_configured", + "cloudwatch_changes_to_network_route_tables_alarm_configured", + "cloudwatch_changes_to_vpcs_alarm_configured", + "config_recorder_all_regions_enabled", + "ec2_instance_imdsv2_enabled", + "guardduty_is_enabled", + "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", + "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", + "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", + "cloudwatch_log_metric_filter_authentication_failures", + "cloudwatch_log_metric_filter_sign_in_without_mfa", + "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", + "cloudwatch_log_metric_filter_policy_changes", + "cloudwatch_log_metric_filter_root_usage", + "cloudwatch_log_metric_filter_security_group_changes", + "cloudwatch_log_metric_filter_unauthorized_api_calls", + "rds_instance_enhanced_monitoring_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "id_sc_4", + "Name": "ID.SC-4", + "Description": "Suppliers and third-party partners are routinely assessed using audits, test results, or other forms of evaluations to confirm they are meeting their contractual obligations.", + "Attributes": [ + { + "ItemId": "id_sc_4", + "Section": "Identify (ID)", + "SubSection": "Supply Chain Risk Management (ID.SC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_cloudwatch_logging_enabled", + "config_recorder_all_regions_enabled", + "ec2_instance_imdsv2_enabled", + "guardduty_is_enabled", + "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", + "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", + "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", + "cloudwatch_log_metric_filter_authentication_failures", + "cloudwatch_log_metric_filter_sign_in_without_mfa", + "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", + "cloudwatch_log_metric_filter_policy_changes", + "cloudwatch_log_metric_filter_root_usage", + "cloudwatch_log_metric_filter_security_group_changes", + "cloudwatch_log_metric_filter_unauthorized_api_calls", + "rds_instance_enhanced_monitoring_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ac_1", + "Name": "PR.AC-1", + "Description": "Identities and credentials are issued, managed, verified, revoked, and audited for authorized devices, users and processes.", + "Attributes": [ + { + "ItemId": "ac_1", + "Section": "Protect (PR)", + "SubSection": "Identity Management and Access Control (PR.AC)", + "Service": "aws" + } + ], + "Checks": [ + "iam_password_policy_reuse_24", + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges", + "iam_inline_policy_no_administrative_privileges", + "iam_no_root_access_key", + "iam_rotate_access_key_90_days", + "iam_user_accesskey_unused", + "iam_user_console_access_unused", + "secretsmanager_automatic_rotation_enabled" + ] + }, + { + "Id": "ac_3", + "Name": "PR.AC-3", + "Description": "Remote access is managed.", + "Attributes": [ + { + "ItemId": "ac_3", + "Section": "Protect (PR)", + "SubSection": "Identity Management and Access Control (PR.AC)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_ebs_public_snapshot", + "ec2_instance_public_ip", + "emr_cluster_master_nodes_no_public_ip", + "iam_root_hardware_mfa_enabled", + "iam_root_mfa_enabled", + "iam_user_mfa_enabled_console_access", + "awslambda_function_not_publicly_accessible", + "awslambda_function_url_public", + "rds_instance_no_public_access", + "rds_snapshots_public_access", + "redshift_cluster_public_access", + "s3_bucket_public_access", + "s3_bucket_policy_public_write_access", + "s3_account_level_public_access_blocks", + "sagemaker_notebook_instance_without_direct_internet_access_configured", + "ec2_securitygroup_default_restrict_traffic", + "ec2_networkacl_allow_ingress_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22" + ] + }, + { + "Id": "ac_4", + "Name": "PR.AC-4", + "Description": "Access permissions and authorizations are managed, incorporating the principles of least privilege and separation of duties.", + "Attributes": [ + { + "ItemId": "ac_4", + "Section": "Protect (PR)", + "SubSection": "Identity Management and Access Control (PR.AC)", + "Service": "aws" + } + ], + "Checks": [ + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges", + "iam_inline_policy_no_administrative_privileges", + "iam_no_root_access_key", + "iam_user_accesskey_unused", + "iam_user_console_access_unused" + ] + }, + { + "Id": "ac_5", + "Name": "PR.AC-5", + "Description": "Network integrity is protected (e.g., network segregation, network segmentation).", + "Attributes": [ + { + "ItemId": "ac_5", + "Section": "Protect (PR)", + "SubSection": "Identity Management and Access Control (PR.AC)", + "Service": "aws" + } + ], + "Checks": [ + "acm_certificates_expiration_check", + "ec2_ebs_public_snapshot", + "ec2_instance_public_ip", + "emr_cluster_master_nodes_no_public_ip", + "awslambda_function_not_publicly_accessible", + "awslambda_function_url_public", + "rds_instance_no_public_access", + "rds_snapshots_public_access", + "redshift_cluster_public_access", + "s3_bucket_public_access", + "s3_bucket_policy_public_write_access", + "s3_account_level_public_access_blocks", + "sagemaker_notebook_instance_without_direct_internet_access_configured", + "ec2_securitygroup_default_restrict_traffic", + "ec2_networkacl_allow_ingress_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22" + ] + }, + { + "Id": "ac_6", + "Name": "PR.AC-6", + "Description": "Identities are proofed and bound to credentials and asserted in interactions.", + "Attributes": [ + { + "ItemId": "ac_6", + "Section": "Protect (PR)", + "SubSection": "Identity Management and Access Control (PR.AC)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "redshift_cluster_audit_logging", + "s3_bucket_server_access_logging_enabled" + ] + }, + { + "Id": "ac_7", + "Name": "PR.AC-7", + "Description": "Users, devices, and other assets are authenticated (e.g., single-factor, multi-factor) commensurate with the risk of the transaction (e.g., individuals' security and privacy risks and other organizational risks).", + "Attributes": [ + { + "ItemId": "ac_7", + "Section": "Protect (PR)", + "SubSection": "Identity Management and Access Control (PR.AC)", + "Service": "iam" + } + ], + "Checks": [ + "iam_root_hardware_mfa_enabled", + "iam_root_mfa_enabled", + "iam_user_mfa_enabled_console_access" + ] + }, + { + "Id": "ds_1", + "Name": "PR.DS-1", + "Description": "Data-at-rest is protected.", + "Attributes": [ + { + "ItemId": "ds_1", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_kms_encryption_enabled", + "ec2_ebs_volume_encryption", + "efs_encryption_at_rest_enabled", + "opensearch_service_domains_encryption_at_rest_enabled", + "cloudwatch_log_group_kms_encryption_enabled", + "rds_instance_storage_encrypted", + "s3_bucket_default_encryption", + "sagemaker_notebook_instance_encryption_enabled", + "sns_topics_kms_encryption_at_rest_enabled" + ] + }, + { + "Id": "ds_2", + "Name": "PR.DS-2", + "Description": "Data-in-transit is protected.", + "Attributes": [ + { + "ItemId": "ds_2", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "acm_certificates_expiration_check", + "elb_ssl_listeners", + "opensearch_service_domains_node_to_node_encryption_enabled", + "s3_bucket_secure_transport_policy" + ] + }, + { + "Id": "ds_3", + "Name": "PR.DS-3", + "Description": "Assets are formally managed throughout removal, transfers, and disposition.", + "Attributes": [ + { + "ItemId": "ds_3", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_instance_managed_by_ssm", + "ssm_managed_compliant_patching", + "ec2_elastic_ip_unassigned" + ] + }, + { + "Id": "ds_4", + "Name": "PR.DS-4", + "Description": "Adequate capacity to ensure availability is maintained.", + "Attributes": [ + { + "ItemId": "ds_4", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "elbv2_deletion_protection", + "rds_instance_enhanced_monitoring_enabled", + "rds_instance_backup_enabled", + "rds_instance_multi_az", + "s3_bucket_object_versioning" + ] + }, + { + "Id": "ds_5", + "Name": "PR.DS-5", + "Description": "Protections against data leaks are implemented.", + "Attributes": [ + { + "ItemId": "ds_5", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "ec2_ebs_public_snapshot", + "elbv2_logging_enabled", + "elb_logging_enabled", + "guardduty_is_enabled", + "awslambda_function_url_public", + "rds_instance_no_public_access", + "rds_snapshots_public_access", + "redshift_cluster_public_access", + "s3_bucket_server_access_logging_enabled", + "s3_bucket_public_access", + "s3_bucket_policy_public_write_access", + "s3_account_level_public_access_blocks", + "sagemaker_notebook_instance_without_direct_internet_access_configured", + "securityhub_enabled", + "vpc_flow_logs_enabled" + ] + }, + { + "Id": "ds_6", + "Name": "PR.DS-6", + "Description": "Integrity checking mechanisms are used to verify software, firmware, and information integrity.", + "Attributes": [ + { + "ItemId": "ds_6", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "cloudtrail" + } + ], + "Checks": [ + "cloudtrail_log_file_validation_enabled" + ] + }, + { + "Id": "ds_7", + "Name": "PR.DS-7", + "Description": "The development and testing environment(s) are separate from the production environment.", + "Attributes": [ + { + "ItemId": "ds_7", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_log_file_validation_enabled", + "ec2_instance_managed_by_ssm", + "ec2_instance_older_than_specific_days", + "elbv2_deletion_protection", + "ssm_managed_compliant_patching", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22" + ] + }, + { + "Id": "ds_8", + "Name": "PR.DS-8", + "Description": "Integrity checking mechanisms are used to verify hardware integrity.", + "Attributes": [ + { + "ItemId": "ds_8", + "Section": "Protect (PR)", + "SubSection": "Data Security (PR.DS)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_instance_managed_by_ssm", + "securityhub_enabled" + ] + }, + { + "Id": "ip_1", + "Name": "PR.IP-1", + "Description": "A baseline configuration of information technology/industrial control systems is created and maintained incorporating security principles (e.g. concept of least functionality).", + "Attributes": [ + { + "ItemId": "ip_1", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_instance_managed_by_ssm", + "ec2_instance_older_than_specific_days", + "ssm_managed_compliant_patching" + ] + }, + { + "Id": "ip_2", + "Name": "PR.IP-2", + "Description": "A System Development Life Cycle to manage systems is implemented.", + "Attributes": [ + { + "ItemId": "ip_2", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_instance_managed_by_ssm" + ] + }, + { + "Id": "ip_3", + "Name": "PR.IP-3", + "Description": "Configuration change control processes are in place.", + "Attributes": [ + { + "ItemId": "ip_3", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "elb" + } + ], + "Checks": [ + "elbv2_deletion_protection" + ] + }, + { + "Id": "ip_4", + "Name": "PR.IP-4", + "Description": "Backups of information are conducted, maintained, and tested periodically.", + "Attributes": [ + { + "ItemId": "ip_4", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "aws" + } + ], + "Checks": [ + "dynamodb_tables_pitr_enabled", + "rds_instance_backup_enabled", + "s3_bucket_object_versioning" + ] + }, + { + "Id": "ip_7", + "Name": "PR.IP-7", + "Description": "Protection processes are improved.", + "Attributes": [ + { + "ItemId": "ip_7", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "ec2" + } + ], + "Checks": [] + }, + { + "Id": "ip_8", + "Name": "PR.IP-8", + "Description": "Effectiveness of protection technologies is shared.", + "Attributes": [ + { + "ItemId": "ip_8", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_ebs_public_snapshot", + "ec2_instance_public_ip", + "eks_cluster_not_publicly_accessible", + "emr_cluster_master_nodes_no_public_ip", + "awslambda_function_url_public", + "rds_instance_no_public_access", + "rds_snapshots_public_access", + "redshift_cluster_public_access", + "s3_bucket_public_access", + "s3_bucket_policy_public_write_access", + "s3_account_level_public_access_blocks", + "sagemaker_notebook_instance_without_direct_internet_access_configured" + ] + }, + { + "Id": "ip_9", + "Name": "PR.IP-9", + "Description": "Response plans (Incident Response and Business Continuity) and recovery plans (Incident Recovery and Disaster Recovery) are in place and managed.", + "Attributes": [ + { + "ItemId": "ip_9", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "aws" + } + ], + "Checks": [ + "dynamodb_tables_pitr_enabled", + "efs_have_backup_enabled", + "elbv2_deletion_protection", + "rds_instance_backup_enabled", + "rds_instance_multi_az", + "redshift_cluster_automated_snapshot", + "s3_bucket_object_versioning" + ] + }, + { + "Id": "ip_12", + "Name": "PR.IP-12", + "Description": "A vulnerability management plan is developed and implemented.", + "Attributes": [ + { + "ItemId": "ip_12", + "Section": "Protect (PR)", + "SubSection": "Information Protection Processes and Procedures (PR.IP)", + "Service": "aws" + } + ], + "Checks": [ + "config_recorder_all_regions_enabled", + "ec2_instance_managed_by_ssm", + "ssm_managed_compliant_patching" + ] + }, + { + "Id": "ma_2", + "Name": "PR.MA-2", + "Description": "Remote maintenance of organizational assets is approved, logged, and performed in a manner that prevents unauthorized access.", + "Attributes": [ + { + "ItemId": "ma_2", + "Section": "Protect (PR)", + "SubSection": "Maintenance (PR.MA)", + "Service": "cloudtrail" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled" + ] + }, + { + "Id": "pt_1", + "Name": "PR.PT-1", + "Description": "Audit/log records are determined, documented, implemented, and reviewed in accordance with policy.", + "Attributes": [ + { + "ItemId": "pt_1", + "Section": "Protect (PR)", + "SubSection": "Protective Technology (PR.PT)", + "Service": "aws" + } + ], + "Checks": [ + "apigateway_restapi_logging_enabled", + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "s3_bucket_server_access_logging_enabled", + "vpc_flow_logs_enabled" + ] + }, + { + "Id": "pt_3", + "Name": "PR.PT-3", + "Description": "The principle of least functionality is incorporated by configuring systems to provide only essential capabilities.", + "Attributes": [ + { + "ItemId": "pt_3", + "Section": "Protect (PR)", + "SubSection": "Protective Technology (PR.PT)", + "Service": "aws" + } + ], + "Checks": [ + "ec2_ebs_public_snapshot", + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges", + "iam_inline_policy_no_administrative_privileges", + "iam_no_root_access_key", + "awslambda_function_url_public", + "rds_snapshots_public_access", + "redshift_cluster_public_access", + "s3_bucket_public_access", + "s3_bucket_policy_public_write_access", + "s3_account_level_public_access_blocks" + ] + }, + { + "Id": "pt_4", + "Name": "PR.PT-4", + "Description": "Communications and control networks are protected.", + "Attributes": [ + { + "ItemId": "pt_4", + "Section": "Protect (PR)", + "SubSection": "Protective Technology (PR.PT)", + "Service": "aws" + } + ], + "Checks": [ + "awslambda_function_not_publicly_accessible", + "rds_instance_no_public_access", + "redshift_cluster_public_access", + "ec2_networkacl_allow_ingress_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22" + ] + }, + { + "Id": "pt_5", + "Name": "PR.PT-5", + "Description": "Mechanisms (e.g., failsafe, load balancing, hot swap) are implemented to achieve resilience requirements in normal and adverse situations.", + "Attributes": [ + { + "ItemId": "pt_5", + "Section": "Protect (PR)", + "SubSection": "Protective Technology (PR.PT)", + "Service": "aws" + } + ], + "Checks": [ + "elbv2_deletion_protection", + "rds_instance_backup_enabled", + "rds_instance_multi_az", + "s3_bucket_object_versioning" + ] + }, + { + "Id": "ae_1", + "Name": "DE.AE-1", + "Description": "A baseline of network operations and expected data flows for users and systems is established and managed.", + "Attributes": [ + { + "ItemId": "ae_1", + "Section": "Detect (DE)", + "SubSection": "Anomalies and Events (DE.AE)", + "Service": "aws" + } + ], + "Checks": [ + "apigateway_restapi_logging_enabled", + "cloudtrail_multi_region_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "redshift_cluster_audit_logging", + "s3_bucket_server_access_logging_enabled", + "ec2_securitygroup_default_restrict_traffic", + "vpc_flow_logs_enabled", + "ec2_networkacl_allow_ingress_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22" + ] + }, + { + "Id": "ae_2", + "Name": "DE.AE-2", + "Description": "Detected events are analyzed to understand attack targets and methods.", + "Attributes": [ + { + "ItemId": "ae_2", + "Section": "Detect (DE)", + "SubSection": "Anomalies and Events (DE.AE)", + "Service": "aws" + } + ], + "Checks": [ + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ae_3", + "Name": "DE.AE-3", + "Description": "Event data are collected and correlated from multiple sources and sensors.", + "Attributes": [ + { + "ItemId": "ae_3", + "Section": "Detect (DE)", + "SubSection": "Anomalies and Events (DE.AE)", + "Service": "aws" + } + ], + "Checks": [ + "apigateway_restapi_logging_enabled", + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "cloudtrail_cloudwatch_logging_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "redshift_cluster_audit_logging", + "s3_bucket_server_access_logging_enabled", + "vpc_flow_logs_enabled" + ] + }, + { + "Id": "ae_4", + "Name": "DE.AE-4", + "Description": "Impact of events is determined.", + "Attributes": [ + { + "ItemId": "ae_4", + "Section": "Detect (DE)", + "SubSection": "Anomalies and Events (DE.AE)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "guardduty_is_enabled", + "guardduty_no_high_severity_findings", + "s3_bucket_server_access_logging_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "ae_5", + "Name": "DE.AE-5", + "Description": "Incident alert thresholds are established.", + "Attributes": [ + { + "ItemId": "ae_5", + "Section": "Detect (DE)", + "SubSection": "Anomalies and Events (DE.AE)", + "Service": "aws" + } + ], + "Checks": [ + "cloudwatch_changes_to_network_acls_alarm_configured", + "cloudwatch_changes_to_network_gateways_alarm_configured", + "cloudwatch_changes_to_network_route_tables_alarm_configured", + "cloudwatch_changes_to_vpcs_alarm_configured" + ] + }, + { + "Id": "cm_1", + "Name": "DE.CM-1", + "Description": "The network is monitored to detect potential cybersecurity events.", + "Attributes": [ + { + "ItemId": "cm_1", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "apigateway_restapi_logging_enabled", + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "guardduty_is_enabled", + "s3_bucket_server_access_logging_enabled", + "securityhub_enabled", + "vpc_flow_logs_enabled" + ] + }, + { + "Id": "cm_2", + "Name": "DE.CM-2", + "Description": "The physical environment is monitored to detect potential cybersecurity events.", + "Attributes": [ + { + "ItemId": "cm_2", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_cloudwatch_logging_enabled", + "cloudwatch_changes_to_network_acls_alarm_configured", + "cloudwatch_changes_to_network_gateways_alarm_configured", + "cloudwatch_changes_to_network_route_tables_alarm_configured", + "cloudwatch_changes_to_vpcs_alarm_configured", + "config_recorder_all_regions_enabled", + "ec2_instance_imdsv2_enabled", + "guardduty_is_enabled", + "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", + "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", + "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", + "cloudwatch_log_metric_filter_authentication_failures", + "cloudwatch_log_metric_filter_sign_in_without_mfa", + "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", + "cloudwatch_log_metric_filter_policy_changes", + "cloudwatch_log_metric_filter_root_usage", + "cloudwatch_log_metric_filter_security_group_changes", + "cloudwatch_log_metric_filter_unauthorized_api_calls", + "rds_instance_enhanced_monitoring_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "cm_3", + "Name": "DE.CM-3", + "Description": "Personnel activity is monitored to detect potential cybersecurity events.", + "Attributes": [ + { + "ItemId": "cm_3", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "guardduty_is_enabled", + "s3_bucket_server_access_logging_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "cm_4", + "Name": "DE.CM-4", + "Description": "Malicious code is detected.", + "Attributes": [ + { + "ItemId": "cm_4", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "guardduty_is_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "cm_5", + "Name": "DE.CM-5", + "Description": "Unauthorized mobile code is detected.", + "Attributes": [ + { + "ItemId": "cm_5", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_cloudwatch_logging_enabled", + "cloudwatch_changes_to_network_acls_alarm_configured", + "cloudwatch_changes_to_network_gateways_alarm_configured", + "cloudwatch_changes_to_network_route_tables_alarm_configured", + "cloudwatch_changes_to_vpcs_alarm_configured", + "ec2_instance_imdsv2_enabled", + "elbv2_waf_acl_attached", + "guardduty_is_enabled", + "guardduty_no_high_severity_findings", + "securityhub_enabled" + ] + }, + { + "Id": "cm_6", + "Name": "DE.CM-6", + "Description": "External service provider activity is monitored to detect potential cybersecurity events.", + "Attributes": [ + { + "ItemId": "cm_6", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "guardduty_is_enabled", + "s3_bucket_server_access_logging_enabled", + "securityhub_enabled" + ] + }, + { + "Id": "cm_7", + "Name": "DE.CM-7", + "Description": "Monitoring for unauthorized personnel, connections, devices, and software is performed.", + "Attributes": [ + { + "ItemId": "cm_7", + "Section": "Detect (DE)", + "SubSection": "Security Continuous Monitoring (DE.CM)", + "Service": "aws" + } + ], + "Checks": [ + "apigateway_restapi_logging_enabled", + "cloudtrail_multi_region_enabled", + "cloudtrail_s3_dataevents_read_enabled", + "cloudtrail_s3_dataevents_write_enabled", + "elbv2_logging_enabled", + "elb_logging_enabled", + "guardduty_is_enabled", + "s3_bucket_server_access_logging_enabled", + "securityhub_enabled", + "vpc_flow_logs_enabled" + ] + }, + { + "Id": "dp_4", + "Name": "DE.DP-4", + "Description": "Event detection information is communicated.", + "Attributes": [ + { + "ItemId": "dp_4", + "Section": "Detect (DE)", + "SubSection": "Detection Processes (DE.DP)", + "Service": "aws" + } + ], + "Checks": [ + "cloudtrail_cloudwatch_logging_enabled", + "cloudwatch_changes_to_network_acls_alarm_configured", + "cloudwatch_changes_to_network_gateways_alarm_configured", + "cloudwatch_changes_to_network_route_tables_alarm_configured", + "cloudwatch_changes_to_vpcs_alarm_configured", + "ec2_instance_imdsv2_enabled", + "elbv2_waf_acl_attached", + "guardduty_is_enabled", + "guardduty_no_high_severity_findings", + "securityhub_enabled" + ] + }, + { + "Id": "dp_5", + "Name": "DE.DP-5", + "Description": "Detection processes are continuously improved.", + "Attributes": [ + { + "ItemId": "dp_5", + "Section": "Detect (DE)", + "SubSection": "Detection Processes (DE.DP)", + "Service": "ec2" + } + ], + "Checks": [ + "ec2_instance_imdsv2_enabled" + ] + }, + { + "Id": "an_2", + "Name": "RS.AN-2", + "Description": "The impact of the incident is understood.", + "Attributes": [ + { + "ItemId": "an_2", + "Section": "Respond (RS)", + "SubSection": "Analysis (RS.AN)", + "Service": "guardduty" + } + ], + "Checks": [ + "guardduty_no_high_severity_findings" + ] + }, + { + "Id": "mi_3", + "Name": "RS.MI-3", + "Description": "Newly identified vulnerabilities are mitigated or documented as accepted risks.", + "Attributes": [ + { + "ItemId": "mi_3", + "Section": "Respond (RS)", + "SubSection": "Mitigation (RS.MI)", + "Service": "guardduty" + } + ], + "Checks": [ + "guardduty_no_high_severity_findings" + ] + }, + { + "Id": "rp_1", + "Name": "RS.RP-1", + "Description": "Response plan is executed during or after an incident.", + "Attributes": [ + { + "ItemId": "rp_1", + "Section": "Respond (RS)", + "SubSection": "Response Planning (RS.RP)", + "Service": "aws" + } + ], + "Checks": [ + "dynamodb_tables_pitr_enabled", + "efs_have_backup_enabled", + "elbv2_deletion_protection", + "rds_instance_backup_enabled", + "rds_instance_multi_az", + "redshift_cluster_automated_snapshot", + "s3_bucket_object_versioning" + ] + }, + { + "Id": "rc_rp_1", + "Name": "RC.RP-1", + "Description": "Recovery plan is executed during or after a cybersecurity incident.", + "Attributes": [ + { + "ItemId": "rc_rp_1", + "Section": "Recover (RC)", + "SubSection": "Recovery Planning (RC.RP)", + "Service": "aws" + } + ], + "Checks": [ + "dynamodb_tables_pitr_enabled", + "efs_have_backup_enabled", + "elbv2_deletion_protection", + "rds_instance_backup_enabled", + "rds_instance_multi_az", + "redshift_cluster_automated_snapshot", + "s3_bucket_object_versioning" + ] + } + ] +} + diff --git a/prowler/compliance/azure/ens_rd2022_azure.json b/prowler/compliance/azure/ens_rd2022_azure.json index 9c5fd543cd..5078c6567e 100644 --- a/prowler/compliance/azure/ens_rd2022_azure.json +++ b/prowler/compliance/azure/ens_rd2022_azure.json @@ -1,6 +1,6 @@ { "Framework": "ENS", - "Name": "ENS RD 311/2022", + "Name": "ENS RD 311/2022 - Categoría Alta", "Version": "RD2022", "Provider": "AZURE", "Description": "The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", diff --git a/prowler/compliance/azure/nis2_azure.json b/prowler/compliance/azure/nis2_azure.json index 052ee1e449..5c48c22f6b 100644 --- a/prowler/compliance/azure/nis2_azure.json +++ b/prowler/compliance/azure/nis2_azure.json @@ -1,6 +1,6 @@ { "Framework": "NIS2", - "Name": "Network and Information Security Directive (Directive (EU) 2022/2555)", + "Name": "NIS2 - Network and Information Security Directive (Directive (EU) 2022/2555)", "Version": "", "Provider": "Azure", "Description": "ANNEX to the Commission Implementing Regulation laying down rules for the application of Directive (EU) 2022/2555 as regards technical and methodological requirements of cybersecurity risk-management measures and further specification of the cases in which an incident is considered to be significant with regard to DNS service providers, TLD name registries, cloud computing service providers, data centre service providers, content delivery network providers, managed service providers, managed security service providers, providers of online market places, of online search engines and of social networking services platforms, and trust service providers", diff --git a/prowler/compliance/gcp/ens_rd2022_gcp.json b/prowler/compliance/gcp/ens_rd2022_gcp.json index cc0a1bfcd4..8315123f79 100644 --- a/prowler/compliance/gcp/ens_rd2022_gcp.json +++ b/prowler/compliance/gcp/ens_rd2022_gcp.json @@ -1,6 +1,6 @@ { "Framework": "ENS", - "Name": "ENS RD 311/2022", + "Name": "ENS RD 311/2022 - Categoría Alta", "Version": "RD2022", "Provider": "GCP", "Description": "The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", diff --git a/prowler/compliance/gcp/hipaa_gcp.json b/prowler/compliance/gcp/hipaa_gcp.json new file mode 100644 index 0000000000..6bacc72e9e --- /dev/null +++ b/prowler/compliance/gcp/hipaa_gcp.json @@ -0,0 +1,415 @@ +{ + "Framework": "HIPAA", + "Name": "HIPAA compliance framework for GCP", + "Version": "", + "Provider": "GCP", + "Description": "The Health Insurance Portability and Accountability Act of 1996 (HIPAA) is legislation that helps US workers to retain health insurance coverage when they change or lose jobs. The legislation also seeks to encourage electronic health records to improve the efficiency and quality of the US healthcare system through improved information sharing. This framework maps HIPAA requirements to Google Cloud Platform (GCP) security best practices.", + "Requirements": [ + { + "Id": "164_308_a_1_ii_a", + "Name": "164.308(a)(1)(ii)(A) Risk analysis", + "Description": "Conduct an accurate and thorough assessment of the potential risks and vulnerabilities to the confidentiality, integrity, and availability of electronic protected health information held by the covered entity or business associate.", + "Attributes": [ + { + "ItemId": "164_308_a_1_ii_a", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "iam_cloud_asset_inventory_enabled", + "securitycenter_security_health_analytics_enabled", + "essentialcontacts_security_contacts_configured" + ] + }, + { + "Id": "164_308_a_1_ii_b", + "Name": "164.308(a)(1)(ii)(B) Risk Management", + "Description": "Implement security measures sufficient to reduce risks and vulnerabilities to a reasonable and appropriate level to comply with 164.306(a): Ensure the confidentiality, integrity, and availability of all electronic protected health information the covered entity or business associate creates, receives, maintains, or transmits.", + "Attributes": [ + { + "ItemId": "164_308_a_1_ii_b", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudstorage_bucket_encryption", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_access", + "cloudsql_instance_automatic_backups_enabled", + "cloudsql_instance_encryption_enabled", + "cloudsql_instance_public_access", + "compute_instance_public_ip", + "compute_disk_encryption_enabled", + "compute_firewall_rdp_access_from_internet_restricted", + "compute_firewall_ssh_access_from_internet_restricted", + "compute_network_legacy_network_not_used", + "gke_cluster_master_authorized_networks_enabled", + "gke_cluster_private_cluster_enabled", + "iam_sa_no_administrative_privileges", + "iam_no_service_roles_at_project_level", + "bigquery_dataset_public_access", + "bigquery_dataset_cmek_encryption", + "kms_key_rotation_enabled" + ] + }, + { + "Id": "164_308_a_1_ii_d", + "Name": "164.308(a)(1)(ii)(D) Information system activity review", + "Description": "Implement procedures to regularly review records of information system activity, such as audit logs, access reports, and security incident tracking reports.", + "Attributes": [ + { + "ItemId": "164_308_a_1_ii_d", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "logging_sink_created", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled" + ] + }, + { + "Id": "164_308_a_3_i", + "Name": "164.308(a)(3)(i) Workforce security", + "Description": "Implement policies and procedures to ensure that all members of its workforce have appropriate access to electronic protected health information.", + "Attributes": [ + { + "ItemId": "164_308_a_3_i", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "iam_sa_no_administrative_privileges", + "iam_no_service_roles_at_project_level", + "iam_role_kms_enforce_separation_of_duties", + "iam_role_sa_enforce_separation_of_duties", + "iam_sa_no_user_managed_keys", + "iam_sa_user_managed_key_unused" + ] + }, + { + "Id": "164_308_a_4_i", + "Name": "164.308(a)(4)(i) Information access management", + "Description": "Implement policies and procedures for authorizing access to electronic protected health information that are consistent with the applicable requirements of subpart E of this part.", + "Attributes": [ + { + "ItemId": "164_308_a_4_i", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "iam_account_access_approval_enabled", + "iam_sa_no_administrative_privileges", + "iam_no_service_roles_at_project_level", + "iam_organization_essential_contacts_configured", + "cloudstorage_bucket_public_access", + "cloudsql_instance_public_access", + "bigquery_dataset_public_access" + ] + }, + { + "Id": "164_308_a_5_ii_c", + "Name": "164.308(a)(5)(ii)(C) Log-in monitoring", + "Description": "Procedures for monitoring log-in attempts and reporting discrepancies.", + "Attributes": [ + { + "ItemId": "164_308_a_5_ii_c", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "logging_sink_created", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled" + ] + }, + { + "Id": "164_308_a_6_ii", + "Name": "164.308(a)(6)(ii) Response and reporting", + "Description": "Identify and respond to suspected or known security incidents; mitigate, to the extent practicable, harmful effects of security incidents that are known to the covered entity or business associate; and document security incidents and their outcomes.", + "Attributes": [ + { + "ItemId": "164_308_a_6_ii", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "securitycenter_security_health_analytics_enabled", + "essentialcontacts_security_contacts_configured", + "logging_sink_created" + ] + }, + { + "Id": "164_308_a_7_i", + "Name": "164.308(a)(7)(i) Contingency plan", + "Description": "Establish (and implement as needed) policies and procedures for responding to an emergency or other occurrence (for example, fire, vandalism, system failure, and natural disaster) that damages systems that contain electronic protected health information.", + "Attributes": [ + { + "ItemId": "164_308_a_7_i", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudsql_instance_automatic_backups_enabled", + "compute_disk_snapshot_encryption_enabled", + "gke_cluster_stackdriver_logging_enabled" + ] + }, + { + "Id": "164_308_a_7_ii_a", + "Name": "164.308(a)(7)(ii)(A) Data backup plan", + "Description": "Establish and implement procedures to create and maintain retrievable exact copies of electronic protected health information.", + "Attributes": [ + { + "ItemId": "164_308_a_7_ii_a", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudsql_instance_automatic_backups_enabled", + "cloudstorage_bucket_object_versioning", + "compute_disk_snapshot_encryption_enabled" + ] + }, + { + "Id": "164_308_a_7_ii_b", + "Name": "164.308(a)(7)(ii)(B) Disaster recovery plan", + "Description": "Establish (and implement as needed) procedures to restore any loss of data.", + "Attributes": [ + { + "ItemId": "164_308_a_7_ii_b", + "Section": "164.308 Administrative Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudsql_instance_automatic_backups_enabled", + "cloudsql_instance_point_in_time_recovery_enabled", + "cloudstorage_bucket_object_versioning" + ] + }, + { + "Id": "164_310_a_1", + "Name": "164.310(a)(1) Facility access controls", + "Description": "Implement policies and procedures to limit physical access to its electronic information systems and the facility or facilities in which they are housed, while ensuring that properly authorized access is allowed.", + "Attributes": [ + { + "ItemId": "164_310_a_1", + "Section": "164.310 Physical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "compute_instance_public_ip", + "compute_firewall_rdp_access_from_internet_restricted", + "compute_firewall_ssh_access_from_internet_restricted", + "gke_cluster_private_cluster_enabled" + ] + }, + { + "Id": "164_310_d_1", + "Name": "164.310(d)(1) Device and media controls", + "Description": "Implement policies and procedures that govern the receipt and removal of hardware and electronic media that contain electronic protected health information into and out of a facility, and the movement of these items within the facility.", + "Attributes": [ + { + "ItemId": "164_310_d_1", + "Section": "164.310 Physical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "compute_disk_encryption_enabled", + "compute_disk_snapshot_encryption_enabled", + "cloudstorage_bucket_encryption" + ] + }, + { + "Id": "164_312_a_1", + "Name": "164.312(a)(1) Access control", + "Description": "Implement technical policies and procedures for electronic information systems that maintain electronic protected health information to allow access only to those persons or software programs that have been granted access rights as specified in 164.308(a)(4).", + "Attributes": [ + { + "ItemId": "164_312_a_1", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "iam_sa_no_administrative_privileges", + "iam_no_service_roles_at_project_level", + "iam_account_access_approval_enabled", + "cloudstorage_bucket_public_access", + "cloudstorage_bucket_uniform_access", + "cloudsql_instance_public_access", + "bigquery_dataset_public_access", + "compute_instance_public_ip", + "gke_cluster_private_cluster_enabled" + ] + }, + { + "Id": "164_312_a_2_i", + "Name": "164.312(a)(2)(i) Unique user identification", + "Description": "Assign a unique name and/or number for identifying and tracking user identity.", + "Attributes": [ + { + "ItemId": "164_312_a_2_i", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "iam_sa_no_user_managed_keys", + "iam_sa_user_managed_key_unused" + ] + }, + { + "Id": "164_312_a_2_iv", + "Name": "164.312(a)(2)(iv) Encryption and decryption", + "Description": "Implement a mechanism to encrypt and decrypt electronic protected health information.", + "Attributes": [ + { + "ItemId": "164_312_a_2_iv", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudstorage_bucket_encryption", + "cloudsql_instance_encryption_enabled", + "compute_disk_encryption_enabled", + "compute_disk_snapshot_encryption_enabled", + "bigquery_dataset_cmek_encryption", + "kms_key_rotation_enabled" + ] + }, + { + "Id": "164_312_b", + "Name": "164.312(b) Audit controls", + "Description": "Implement hardware, software, and/or procedural mechanisms that record and examine activity in information systems that contain or use electronic protected health information.", + "Attributes": [ + { + "ItemId": "164_312_b", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "logging_sink_created", + "logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled", + "logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled", + "logging_log_metric_filter_and_alert_for_custom_role_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled", + "logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled", + "logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled", + "logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled", + "gke_cluster_stackdriver_logging_enabled" + ] + }, + { + "Id": "164_312_c_1", + "Name": "164.312(c)(1) Integrity", + "Description": "Implement policies and procedures to protect electronic protected health information from improper alteration or destruction.", + "Attributes": [ + { + "ItemId": "164_312_c_1", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudstorage_bucket_object_versioning", + "cloudsql_instance_automatic_backups_enabled", + "cloudsql_instance_point_in_time_recovery_enabled", + "kms_key_rotation_enabled" + ] + }, + { + "Id": "164_312_d", + "Name": "164.312(d) Person or entity authentication", + "Description": "Implement procedures to verify that a person or entity seeking access to electronic protected health information is the one claimed.", + "Attributes": [ + { + "ItemId": "164_312_d", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "iam_account_access_approval_enabled", + "iam_sa_no_user_managed_keys" + ] + }, + { + "Id": "164_312_e_1", + "Name": "164.312(e)(1) Transmission security", + "Description": "Implement technical security measures to guard against unauthorized access to electronic protected health information that is being transmitted over an electronic communications network.", + "Attributes": [ + { + "ItemId": "164_312_e_1", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudstorage_bucket_encryption", + "compute_firewall_rdp_access_from_internet_restricted", + "compute_firewall_ssh_access_from_internet_restricted", + "cloudsql_instance_ssl_required", + "gke_cluster_master_authorized_networks_enabled" + ] + }, + { + "Id": "164_312_e_2_i", + "Name": "164.312(e)(2)(i) Integrity controls", + "Description": "Implement security measures to ensure that electronically transmitted electronic protected health information is not improperly modified without detection until disposed of.", + "Attributes": [ + { + "ItemId": "164_312_e_2_i", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudstorage_bucket_object_versioning", + "cloudsql_instance_automatic_backups_enabled", + "logging_sink_created" + ] + }, + { + "Id": "164_312_e_2_ii", + "Name": "164.312(e)(2)(ii) Encryption", + "Description": "Implement a mechanism to encrypt electronic protected health information whenever deemed appropriate.", + "Attributes": [ + { + "ItemId": "164_312_e_2_ii", + "Section": "164.312 Technical Safeguards", + "Service": "gcp" + } + ], + "Checks": [ + "cloudstorage_bucket_encryption", + "cloudsql_instance_encryption_enabled", + "compute_disk_encryption_enabled", + "bigquery_dataset_cmek_encryption", + "kms_key_rotation_enabled", + "cloudsql_instance_ssl_required" + ] + } + ] +} diff --git a/prowler/compliance/gcp/nis2_gcp.json b/prowler/compliance/gcp/nis2_gcp.json index 9768b2dd3d..14d5477dc0 100644 --- a/prowler/compliance/gcp/nis2_gcp.json +++ b/prowler/compliance/gcp/nis2_gcp.json @@ -1,6 +1,6 @@ { "Framework": "NIS2", - "Name": "Network and Information Security Directive (Directive (EU) 2022/2555)", + "Name": "NIS2 - Network and Information Security Directive (Directive (EU) 2022/2555)", "Version": "", "Provider": "GCP", "Description": "ANNEX to the Commission Implementing Regulation laying down rules for the application of Directive (EU) 2022/2555 as regards technical and methodological requirements of cybersecurity risk-management measures and further specification of the cases in which an incident is considered to be significant with regard to DNS service providers, TLD name registries, cloud computing service providers, data centre service providers, content delivery network providers, managed service providers, managed security service providers, providers of online market places, of online search engines and of social networking services platforms, and trust service providers", diff --git a/prowler/compliance/github/cis_1.0_github.json b/prowler/compliance/github/cis_1.0_github.json index d488b92a00..f016acaabb 100644 --- a/prowler/compliance/github/cis_1.0_github.json +++ b/prowler/compliance/github/cis_1.0_github.json @@ -476,7 +476,9 @@ { "Id": "1.2.2", "Description": "Limit the ability to create repositories to trusted users and teams.", - "Checks": [], + "Checks": [ + "organization_repository_creation_limited" + ], "Attributes": [ { "Section": "1 Source Code", diff --git a/prowler/compliance/oci/__init__.py b/prowler/compliance/oraclecloud/__init__.py similarity index 100% rename from prowler/compliance/oci/__init__.py rename to prowler/compliance/oraclecloud/__init__.py diff --git a/prowler/compliance/oci/cis_3.0_oci.json b/prowler/compliance/oraclecloud/cis_3.0_oraclecloud.json similarity index 99% rename from prowler/compliance/oci/cis_3.0_oci.json rename to prowler/compliance/oraclecloud/cis_3.0_oraclecloud.json index 033a0845e5..76ff7cd7ef 100644 --- a/prowler/compliance/oci/cis_3.0_oci.json +++ b/prowler/compliance/oraclecloud/cis_3.0_oraclecloud.json @@ -2,7 +2,7 @@ "Framework": "CIS", "Name": "CIS Oracle Cloud Infrastructure Foundations Benchmark v3.0.0", "Version": "3.0", - "Provider": "OCI", + "Provider": "OracleCloud", "Description": "The CIS Oracle Cloud Infrastructure Foundations Benchmark provides prescriptive guidance for configuring security options for Oracle Cloud Infrastructure with an emphasis on foundational, testable, and architecture agnostic settings.", "Requirements": [ { diff --git a/prowler/config/config.py b/prowler/config/config.py index b8fbe91074..d925a37d31 100644 --- a/prowler/config/config.py +++ b/prowler/config/config.py @@ -33,7 +33,7 @@ class Provider(str, Enum): IAC = "iac" NHN = "nhn" MONGODBATLAS = "mongodbatlas" - OCI = "oci" + ORACLECLOUD = "oraclecloud" # Compliance diff --git a/prowler/lib/check/check.py b/prowler/lib/check/check.py index 0925c14925..d8f395d7ba 100644 --- a/prowler/lib/check/check.py +++ b/prowler/lib/check/check.py @@ -438,16 +438,8 @@ def execute_checks( service = check_name.split("_")[0] try: try: - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # OCI SDK conflict avoidance - } - provider_directory = provider_directory_map.get( - global_provider.type, global_provider.type - ) - # Import check module - check_module_path = f"prowler.providers.{provider_directory}.services.{service}.{check_name}.{check_name}" + check_module_path = f"prowler.providers.{global_provider.type}.services.{service}.{check_name}.{check_name}" lib = import_check(check_module_path) # Recover functions from check check_to_execute = getattr(lib, check_name) @@ -526,16 +518,8 @@ def execute_checks( ) try: try: - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # oci SDK conflict avoidance - } - provider_directory = provider_directory_map.get( - global_provider.type, global_provider.type - ) - # Import check module - check_module_path = f"prowler.providers.{provider_directory}.services.{service}.{check_name}.{check_name}" + check_module_path = f"prowler.providers.{global_provider.type}.services.{service}.{check_name}.{check_name}" lib = import_check(check_module_path) # Recover functions from check check_to_execute = getattr(lib, check_name) diff --git a/prowler/lib/check/checks_loader.py b/prowler/lib/check/checks_loader.py index c03034b0e4..dab5535d77 100644 --- a/prowler/lib/check/checks_loader.py +++ b/prowler/lib/check/checks_loader.py @@ -1,3 +1,5 @@ +import sys + from colorama import Fore, Style from prowler.lib.check.check import parse_checks_from_file @@ -57,8 +59,24 @@ def load_checks_to_execute( # Handle if there are checks passed using -c/--checks if check_list: + # Validate that all checks exist + available_checks = set(bulk_checks_metadata.keys()) + available_checks.update(check_aliases.keys()) + invalid_checks = [] for check_name in check_list: - checks_to_execute.add(check_name) + if check_name not in available_checks: + invalid_checks.append(check_name) + else: + checks_to_execute.add(check_name) + + if invalid_checks: + logger.critical( + f"Invalid check(s) specified: {', '.join(invalid_checks)}" + ) + logger.critical( + f"Please provide valid check names. Use 'prowler {provider} --list-checks' to see available checks." + ) + sys.exit(1) # Handle if there are some severities passed using --severity elif severities: @@ -66,6 +84,23 @@ def load_checks_to_execute( checks_to_execute.update(check_severities[severity]) if service_list: + # Validate that all services exist + available_services = set() + for metadata in bulk_checks_metadata.values(): + available_services.add(metadata.ServiceName) + + invalid_services = [ + s for s in service_list if s not in available_services + ] + if invalid_services: + logger.critical( + f"Invalid service(s) specified: {', '.join(invalid_services)}" + ) + logger.critical( + f"Please provide valid service names. Use 'prowler {provider} --list-services' to see available services." + ) + sys.exit(1) + checks_from_services = set() for service in service_list: service_checks = CheckMetadata.list( @@ -81,6 +116,21 @@ def load_checks_to_execute( # Handle if there are services passed using -s/--services elif service_list: + # Validate that all services exist + available_services = set() + for metadata in bulk_checks_metadata.values(): + available_services.add(metadata.ServiceName) + + invalid_services = [s for s in service_list if s not in available_services] + if invalid_services: + logger.critical( + f"Invalid service(s) specified: {', '.join(invalid_services)}" + ) + logger.critical( + f"Please provide valid service names. Use 'prowler {provider} --list-services' to see available services." + ) + sys.exit(1) + for service in service_list: checks_to_execute.update( CheckMetadata.list( @@ -103,6 +153,20 @@ def load_checks_to_execute( # Handle if there are categories passed using --categories elif categories: + # Validate that all categories exist + available_categories = set(check_categories.keys()) + invalid_categories = [ + c for c in categories if c not in available_categories + ] + if invalid_categories: + logger.critical( + f"Invalid category(ies) specified: {', '.join(invalid_categories)}" + ) + logger.critical( + f"Please provide valid category names. Use 'prowler {provider} --list-categories' to see available categories." + ) + sys.exit(1) + for category in categories: checks_to_execute.update(check_categories[category]) diff --git a/prowler/lib/check/models.py b/prowler/lib/check/models.py index 2398dc8267..37150f38db 100644 --- a/prowler/lib/check/models.py +++ b/prowler/lib/check/models.py @@ -588,8 +588,17 @@ class Check_Report_GCP(Check_Report): or getattr(resource, "name", None) or "" ) + + # Prefer the explicit resource_name argument, otherwise look for a name attribute on the resource + resource_name_candidate = resource_name or getattr(resource, "name", None) + if not resource_name_candidate and isinstance(resource, dict): + # Some callers pass a dict, so fall back to the dict entry if available + resource_name_candidate = resource.get("name") + if isinstance(resource_name_candidate, str): + # Trim whitespace so empty strings collapse to the default + resource_name_candidate = resource_name_candidate.strip() self.resource_name = ( - resource_name or getattr(resource, "name", "") or "GCP Project" + str(resource_name_candidate) if resource_name_candidate else "GCP Project" ) self.project_id = project_id or getattr(resource, "project_id", "") self.location = ( diff --git a/prowler/lib/check/utils.py b/prowler/lib/check/utils.py index 67dd5cda20..8cf37817c9 100644 --- a/prowler/lib/check/utils.py +++ b/prowler/lib/check/utils.py @@ -46,14 +46,8 @@ def recover_checks_from_provider( # List all available modules in the selected provider and service def list_modules(provider: str, service: str): - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # OCI SDK conflict avoidance - } - provider_directory = provider_directory_map.get(provider, provider) - # This module path requires the full path including "prowler." - module_path = f"prowler.providers.{provider_directory}.services" + module_path = f"prowler.providers.{provider}.services" if service: module_path += f".{service}" return walk_packages( diff --git a/prowler/lib/cli/parser.py b/prowler/lib/cli/parser.py index aaeda914bb..07327e5334 100644 --- a/prowler/lib/cli/parser.py +++ b/prowler/lib/cli/parser.py @@ -26,17 +26,17 @@ class ProwlerArgumentParser: self.parser = argparse.ArgumentParser( prog="prowler", formatter_class=RawTextHelpFormatter, - usage="prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,github,nhn,mongodbatlas,oci,dashboard,iac} ...", + usage="prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,github,nhn,mongodbatlas,oraclecloud,dashboard,iac} ...", epilog=""" Available Cloud Providers: - {aws,azure,gcp,kubernetes,m365,github,iac,llm,nhn,mongodbatlas,oci} + {aws,azure,gcp,kubernetes,m365,github,iac,llm,nhn,mongodbatlas,oraclecloud} aws AWS Provider azure Azure Provider gcp GCP Provider kubernetes Kubernetes Provider m365 Microsoft 365 Provider github GitHub Provider - oci Oracle Cloud Infrastructure Provider + oraclecloud Oracle Cloud Infrastructure Provider iac IaC Provider (Beta) llm LLM Provider (Beta) nhn NHN Provider (Unofficial) @@ -113,6 +113,9 @@ Detailed documentation at https://docs.prowler.com # Microsoft 365 elif sys.argv[1] == "microsoft365": sys.argv[1] = "m365" + # Oracle Cloud Infrastructure + elif sys.argv[1] == "oci": + sys.argv[1] = "oraclecloud" # Parse arguments args = self.parser.parse_args() diff --git a/prowler/lib/outputs/compliance/cis/cis_oci.py b/prowler/lib/outputs/compliance/cis/cis_oraclecloud.py similarity index 92% rename from prowler/lib/outputs/compliance/cis/cis_oci.py rename to prowler/lib/outputs/compliance/cis/cis_oraclecloud.py index 6d11bedbef..19e6e1d8c8 100644 --- a/prowler/lib/outputs/compliance/cis/cis_oci.py +++ b/prowler/lib/outputs/compliance/cis/cis_oraclecloud.py @@ -1,20 +1,20 @@ from prowler.config.config import timestamp from prowler.lib.check.compliance_models import Compliance -from prowler.lib.outputs.compliance.cis.models import OCICISModel +from prowler.lib.outputs.compliance.cis.models import OracleCloudCISModel from prowler.lib.outputs.compliance.compliance_output import ComplianceOutput from prowler.lib.outputs.finding import Finding -class OCICIS(ComplianceOutput): +class OracleCloudCIS(ComplianceOutput): """ - This class represents the OCI CIS compliance output. + This class represents the Oracle Cloud CIS compliance output. Attributes: - _data (list): A list to store transformed data from findings. - _file_descriptor (TextIOWrapper): A file descriptor to write data to a file. Methods: - - transform: Transforms findings into OCI CIS compliance format. + - transform: Transforms findings into Oracle Cloud CIS compliance format. """ def transform( @@ -24,7 +24,7 @@ class OCICIS(ComplianceOutput): compliance_name: str, ) -> None: """ - Transforms a list of findings into OCI CIS compliance format. + Transforms a list of findings into Oracle Cloud CIS compliance format. Parameters: - findings (list): A list of findings. @@ -40,7 +40,7 @@ class OCICIS(ComplianceOutput): for requirement in compliance.Requirements: if requirement.Id in finding_requirements: for attribute in requirement.Attributes: - compliance_row = OCICISModel( + compliance_row = OracleCloudCISModel( Provider=finding.provider, Description=compliance.Description, TenancyId=finding.account_uid, @@ -74,7 +74,7 @@ class OCICIS(ComplianceOutput): for requirement in compliance.Requirements: if not requirement.Checks: for attribute in requirement.Attributes: - compliance_row = OCICISModel( + compliance_row = OracleCloudCISModel( Provider=compliance.Provider.lower(), Description=compliance.Description, TenancyId="", diff --git a/prowler/lib/outputs/compliance/cis/models.py b/prowler/lib/outputs/compliance/cis/models.py index 3168a8c04c..6f3bb45c5f 100644 --- a/prowler/lib/outputs/compliance/cis/models.py +++ b/prowler/lib/outputs/compliance/cis/models.py @@ -207,9 +207,9 @@ class GithubCISModel(BaseModel): Name: str -class OCICISModel(BaseModel): +class OracleCloudCISModel(BaseModel): """ - OCICISModel generates a finding's output in OCI CIS Compliance format. + OracleCloudCISModel generates a finding's output in Oracle Cloud CIS Compliance format. """ Provider: str @@ -248,7 +248,7 @@ CIS_GCP = GCPCISModel CIS_Kubernetes = KubernetesCISModel CIS_M365 = M365CISModel CIS_Github = GithubCISModel -CIS_OCI = OCICISModel +CIS_OracleCloud = OracleCloudCISModel # TODO: Create a parent class for the common fields of CIS and have the specific classes from each provider to inherit from it. diff --git a/prowler/lib/outputs/finding.py b/prowler/lib/outputs/finding.py index 6d3807a46e..87db251156 100644 --- a/prowler/lib/outputs/finding.py +++ b/prowler/lib/outputs/finding.py @@ -309,10 +309,17 @@ class Finding(BaseModel): output_data["auth_method"] = provider.auth_method output_data["account_uid"] = "iac" output_data["account_name"] = "iac" - output_data["resource_name"] = check_output.resource_name - output_data["resource_uid"] = check_output.resource_name - output_data["region"] = check_output.resource_line_range - output_data["resource_line_range"] = check_output.resource_line_range + output_data["resource_name"] = getattr( + check_output, "resource_name", "" + ) + output_data["resource_uid"] = getattr(check_output, "resource_name", "") + # For IaC, resource_line_range only exists on CheckReportIAC, not on Finding objects + output_data["region"] = getattr( + check_output, "resource_line_range", "file" + ) + output_data["resource_line_range"] = getattr( + check_output, "resource_line_range", "" + ) output_data["framework"] = check_output.check_metadata.ServiceName elif provider.type == "llm": @@ -323,7 +330,7 @@ class Finding(BaseModel): output_data["resource_uid"] = check_output.model output_data["region"] = check_output.model - elif provider.type == "oci": + elif provider.type == "oraclecloud": output_data["auth_method"] = ( f"Profile: {get_nested_attribute(provider, 'session.profile')}" ) @@ -407,7 +414,11 @@ class Finding(BaseModel): finding.subscription = list(provider.identity.subscriptions.keys())[0] elif provider.type == "gcp": finding.project_id = list(provider.projects.keys())[0] - elif provider.type == "oci": + elif provider.type == "iac": + # For IaC, we don't have resource_line_range in the Finding model + # It would need to be extracted from the resource metadata if needed + finding.resource_line_range = "" # Set empty for compatibility + elif provider.type == "oraclecloud": finding.compartment_id = getattr(finding, "compartment_id", "") finding.check_metadata = CheckMetadata( diff --git a/prowler/lib/outputs/outputs.py b/prowler/lib/outputs/outputs.py index d7f1f6435a..11355ea5f7 100644 --- a/prowler/lib/outputs/outputs.py +++ b/prowler/lib/outputs/outputs.py @@ -28,7 +28,7 @@ def stdout_report(finding, color, verbose, status, fix): details = finding.check_metadata.CheckID if finding.check_metadata.Provider == "iac": details = finding.check_metadata.CheckID - if finding.check_metadata.Provider == "oci": + if finding.check_metadata.Provider == "oraclecloud": details = finding.region if (verbose or fix) and (not status or finding.status in status): diff --git a/prowler/lib/outputs/summary_table.py b/prowler/lib/outputs/summary_table.py index 03ca23453a..747bae1821 100644 --- a/prowler/lib/outputs/summary_table.py +++ b/prowler/lib/outputs/summary_table.py @@ -67,7 +67,7 @@ def display_summary_table( elif provider.type == "llm": entity_type = "LLM" audited_entities = provider.model - elif provider.type == "oci": + elif provider.type == "oraclecloud": entity_type = "Tenancy" audited_entities = ( provider.identity.tenancy_name diff --git a/prowler/lib/scan/scan.py b/prowler/lib/scan/scan.py index 8afe993f10..61bc6dd684 100644 --- a/prowler/lib/scan/scan.py +++ b/prowler/lib/scan/scan.py @@ -1,4 +1,5 @@ import datetime +from datetime import timezone from types import SimpleNamespace from typing import Generator @@ -25,6 +26,7 @@ from prowler.lib.scan.exceptions.exceptions import ( ) from prowler.providers.common.models import Audit_Metadata, ProviderOutputOptions from prowler.providers.common.provider import Provider +from prowler.providers.iac.iac_provider import IacProvider class Scan: @@ -90,15 +92,25 @@ class Scan: except ValueError: raise ScanInvalidStatusError(f"Invalid status provided: {s}.") - # Load bulk compliance frameworks - self._bulk_compliance_frameworks = Compliance.get_bulk(provider.type) - - # Get bulk checks metadata for the provider - self._bulk_checks_metadata = CheckMetadata.get_bulk(provider.type) - # Complete checks metadata with the compliance framework specification - self._bulk_checks_metadata = update_checks_metadata_with_compliance( - self._bulk_compliance_frameworks, self._bulk_checks_metadata - ) + # Special setup for IaC provider - override inputs to work with traditional flow + if provider.type == "iac": + # IaC doesn't use traditional Prowler checks, so clear all input parameters + # to avoid validation errors and let it flow through the normal logic + checks = None + services = None + excluded_checks = None + excluded_services = None + self._bulk_checks_metadata = {} + self._bulk_compliance_frameworks = {} + else: + # Load bulk compliance frameworks + self._bulk_compliance_frameworks = Compliance.get_bulk(provider.type) + # Get bulk checks metadata for the provider + self._bulk_checks_metadata = CheckMetadata.get_bulk(provider.type) + # Complete checks metadata with the compliance framework specification + self._bulk_checks_metadata = update_checks_metadata_with_compliance( + self._bulk_compliance_frameworks, self._bulk_checks_metadata + ) # Create a list of valid categories valid_categories = set() @@ -148,19 +160,22 @@ class Scan: ) # Load checks to execute - self._checks_to_execute = sorted( - load_checks_to_execute( - bulk_checks_metadata=self._bulk_checks_metadata, - bulk_compliance_frameworks=self._bulk_compliance_frameworks, - check_list=checks, - service_list=services, - compliance_frameworks=compliances, - categories=categories, - severities=severities, - provider=provider.type, - checks_file=None, + if provider.type == "iac": + self._checks_to_execute = ["iac_scan"] # Dummy check name for IaC + else: + self._checks_to_execute = sorted( + load_checks_to_execute( + bulk_checks_metadata=self._bulk_checks_metadata, + bulk_compliance_frameworks=self._bulk_compliance_frameworks, + check_list=checks, + service_list=services, + compliance_frameworks=compliances, + categories=categories, + severities=severities, + provider=provider.type, + checks_file=None, + ) ) - ) # Exclude checks if excluded_checks: @@ -184,9 +199,13 @@ class Scan: self._number_of_checks_to_execute = len(self._checks_to_execute) - service_checks_to_execute = get_service_checks_to_execute( - self._checks_to_execute - ) + # Set up service-based checks tracking + if provider.type == "iac": + service_checks_to_execute = {"iac": set(["iac_scan"])} + else: + service_checks_to_execute = get_service_checks_to_execute( + self._checks_to_execute + ) service_checks_completed = dict() self._service_checks_to_execute = service_checks_to_execute @@ -245,6 +264,9 @@ class Scan: Exception: If any other error occurs during the execution of a check. """ try: + # Initialize check_name for error handling + check_name = None + # Using SimpleNamespace to create a mocked object arguments = SimpleNamespace() @@ -266,21 +288,71 @@ class Scan: start_time = datetime.datetime.now() + # Special handling for IaC provider + if self._provider.type == "iac": + # IaC provider doesn't use regular checks, it runs Trivy directly + if isinstance(self._provider, IacProvider): + logger.info("Running IaC scan with Trivy...") + # Run the IaC scan + iac_reports = self._provider.run() + + # Convert IaC reports to Finding objects + findings = [] + + for report in iac_reports: + # Generate unique UID for the finding + finding_uid = f"{report.check_metadata.CheckID}-{report.resource_name}-{report.resource_line_range}" + + # Convert status string to Status enum + status_enum = ( + Status.FAIL if report.status == "FAIL" else Status.PASS + ) + if report.muted: + status_enum = Status.MUTED + + finding = Finding( + auth_method="Repository", # IaC uses repository as auth method + timestamp=datetime.datetime.now(timezone.utc), + account_uid=self._provider.scan_repository_url or "local", + account_name="IaC Repository", + metadata=report.check_metadata, # Pass the CheckMetadata object directly + uid=finding_uid, + status=status_enum, + status_extended=report.status_extended, + muted=report.muted, + resource_uid=report.resource_name, # For IaC, the file path is the UID + resource_metadata=report.resource, # The raw finding dict + resource_name=report.resource_name, + resource_details=report.resource_details, + resource_tags={}, # IaC doesn't have resource tags + region="global", # IaC doesn't have regions + compliance={}, # IaC doesn't have compliance mappings yet + raw=report.resource, # The raw finding dict + ) + findings.append(finding) + + # Filter the findings by the status + if self._status: + findings = [f for f in findings if f.status in self._status] + + # Update progress and yield findings + self._number_of_checks_completed = 1 + self._number_of_checks_to_execute = 1 + + yield (100.0, findings) + + # Calculate duration + end_time = datetime.datetime.now() + self._duration = int((end_time - start_time).total_seconds()) + return + for check_name in checks_to_execute: try: # Recover service from check name service = get_service_name_from_check_name(check_name) try: - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # OCI SDK conflict avoidance - } - provider_directory = provider_directory_map.get( - self._provider.type, self._provider.type - ) - # Import check module - check_module_path = f"prowler.providers.{provider_directory}.services.{service}.{check_name}.{check_name}" + check_module_path = f"prowler.providers.{self._provider.type}.services.{service}.{check_name}.{check_name}" lib = import_check(check_module_path) # Recover functions from check check_to_execute = getattr(lib, check_name) @@ -349,6 +421,7 @@ class Scan: # Update the scan duration when all checks are completed self._duration = int((datetime.datetime.now() - start_time).total_seconds()) except Exception as error: + check_name = check_name or "Scan error" logger.error( f"{check_name} - {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) diff --git a/prowler/providers/aws/aws_regions_by_service.json b/prowler/providers/aws/aws_regions_by_service.json index 745e36d648..6969414824 100644 --- a/prowler/providers/aws/aws_regions_by_service.json +++ b/prowler/providers/aws/aws_regions_by_service.json @@ -2988,6 +2988,7 @@ "ap-southeast-3", "ap-southeast-4", "ap-southeast-5", + "ap-southeast-6", "ap-southeast-7", "ca-central-1", "ca-west-1", @@ -4574,6 +4575,25 @@ "aws-us-gov": [] } }, + "evs": { + "regions": { + "aws": [ + "ap-northeast-1", + "ap-south-1", + "ap-southeast-1", + "ap-southeast-2", + "ca-central-1", + "eu-central-1", + "eu-west-1", + "eu-west-2", + "us-east-1", + "us-east-2", + "us-west-2" + ], + "aws-cn": [], + "aws-us-gov": [] + } + }, "fargate": { "regions": { "aws": [ diff --git a/prowler/providers/aws/services/account/account_service.py b/prowler/providers/aws/services/account/account_service.py index 08000112ca..2ea4217b17 100644 --- a/prowler/providers/aws/services/account/account_service.py +++ b/prowler/providers/aws/services/account/account_service.py @@ -1,9 +1,9 @@ from typing import Optional -from venv import logger from botocore.client import ClientError from pydantic.v1 import BaseModel +from prowler.lib.logger import logger from prowler.providers.aws.lib.service.service import AWSService diff --git a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json index f2887dd121..4aff28188c 100644 --- a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json +++ b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.metadata.json @@ -13,7 +13,7 @@ "ResourceIdTemplate": "", "Severity": "medium", "ResourceType": "AwsKinesisStream", - "Description": "**Amazon Data Firehose** delivery streams use **server-side encryption at rest** with AWS KMS. For `DirectPut` or database sources, the stream must have KMS encryption enabled. When the source is **Kinesis Data Streams**, the source's encryption is considered. For **MSK** sources, encryption at rest is always applied by AWS.", + "Description": "**Amazon Data Firehose** delivery streams must enable **server-side encryption at rest** with AWS KMS regardless of the source type. Encryption of upstream sources such as **Kinesis Data Streams** or **MSK** does not replace the need to protect the delivery stream itself.", "Risk": "Unencrypted Firehose data at rest can be read if storage or backups are accessed, harming **confidentiality** and **integrity**. Disk-level access, snapshots, or misconfigured destinations enable data exfiltration or tampering. Lacking KMS-backed controls also reduces key rotation, segregation of duties, and auditability.", "RelatedUrl": "", "AdditionalURLs": [ diff --git a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py index 21ca07a920..6245e4b5b7 100644 --- a/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py +++ b/prowler/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest.py @@ -26,23 +26,27 @@ class firehose_stream_encrypted_at_rest(Check): for stream in firehose_client.delivery_streams.values(): report = Check_Report_AWS(metadata=self.metadata(), resource=stream) report.status = "FAIL" - report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled or the source stream is not encrypted." + report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled." - # Encrypted Kinesis Stream source - if stream.delivery_stream_type == "KinesisStreamAsSource": - source_stream = kinesis_client.streams.get( - stream.source.kinesis_stream.kinesis_stream_arn - ) + if stream.kms_encryption == EncryptionStatus.ENABLED: + report.status = "PASS" + report.status_extended = f"Firehose Stream {stream.name} does have at rest encryption enabled." + + elif stream.delivery_stream_type == "KinesisStreamAsSource": + source_stream_arn = stream.source.kinesis_stream.kinesis_stream_arn + source_stream = kinesis_client.streams.get(source_stream_arn, None) if source_stream: - if source_stream.encrypted_at_rest != EncryptionType.NONE: - report.status = "PASS" - report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled but the source stream {source_stream.name} has at rest encryption enabled." + if source_stream.encrypted_at_rest == EncryptionType.KMS: + report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled even though source stream {source_stream.name} has at rest encryption enabled." + else: + report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled and the source stream {source_stream.name} is not encrypted at rest." + else: + report.status_extended = f"Firehose Stream {stream.name} does not have at rest encryption enabled and the referenced source stream could not be found." - # MSK source - check if the MSK cluster has encryption at rest with CMK elif stream.delivery_stream_type == "MSKAsSource": msk_cluster_arn = stream.source.msk.msk_cluster_arn + msk_cluster = None if msk_cluster_arn: - msk_cluster = None for cluster in kafka_client.clusters.values(): if cluster.arn == msk_cluster_arn: msk_cluster = cluster @@ -59,11 +63,6 @@ class firehose_stream_encrypted_at_rest(Check): else: report.status_extended = f"Firehose Stream {stream.name} uses MSK source which always has encryption at rest enabled by AWS." - # Check if the stream has encryption enabled directly (DirectPut or DatabaseAsSource cases) - elif stream.kms_encryption == EncryptionStatus.ENABLED: - report.status = "PASS" - report.status_extended = f"Firehose Stream {stream.name} does have at rest encryption enabled." - findings.append(report) return findings diff --git a/prowler/providers/common/arguments.py b/prowler/providers/common/arguments.py index f2f72cd481..f0af3a283c 100644 --- a/prowler/providers/common/arguments.py +++ b/prowler/providers/common/arguments.py @@ -16,15 +16,9 @@ def init_providers_parser(self): providers = Provider.get_available_providers() for provider in providers: try: - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # OCI SDK conflict avoidance - } - provider_directory = provider_directory_map.get(provider, provider) - getattr( import_module( - f"{providers_path}.{provider_directory}.{provider_arguments_lib_path}" + f"{providers_path}.{provider}.{provider_arguments_lib_path}" ), init_provider_arguments_function, )(self) @@ -38,18 +32,10 @@ def init_providers_parser(self): def validate_provider_arguments(arguments: Namespace) -> tuple[bool, str]: """validate_provider_arguments returns {True, "} if the provider arguments passed are valid and can be used together""" try: - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # OCI SDK conflict avoidance - } - provider_directory = provider_directory_map.get( - arguments.provider, arguments.provider - ) - # Provider function must be located at prowler.providers..lib.arguments.arguments.validate_arguments return getattr( import_module( - f"{providers_path}.{provider_directory}.{provider_arguments_lib_path}" + f"{providers_path}.{arguments.provider}.{provider_arguments_lib_path}" ), validate_provider_arguments_function, )(arguments) diff --git a/prowler/providers/common/provider.py b/prowler/providers/common/provider.py index 1f4493015b..c19d0c468e 100644 --- a/prowler/providers/common/provider.py +++ b/prowler/providers/common/provider.py @@ -146,24 +146,8 @@ class Provider(ABC): @staticmethod def init_global_provider(arguments: Namespace) -> None: try: - # Map CLI provider names to directory names (for cases where they differ) - provider_directory_map = { - "oci": "oraclecloud", # oci SDK conflict avoidance - } - # Map CLI provider names to provider file names (for cases where they differ) - provider_file_map = { - "oci": "oci", # oraclecloud directory but oci_provider.py file - } - - provider_directory = provider_directory_map.get( - arguments.provider, arguments.provider - ) - provider_file = provider_file_map.get( - arguments.provider, arguments.provider - ) - provider_class_path = ( - f"{providers_path}.{provider_directory}.{provider_file}_provider" + f"{providers_path}.{arguments.provider}.{arguments.provider}_provider" ) provider_class_name = f"{arguments.provider.capitalize()}Provider" provider_class = getattr( @@ -291,7 +275,7 @@ class Provider(ABC): mutelist_path=arguments.mutelist_file, fixer_config=fixer_config, ) - elif "oci" in provider_class_name.lower(): + elif "oraclecloud" in provider_class_name.lower(): provider_class( oci_config_file=arguments.oci_config_file, profile=arguments.profile, diff --git a/prowler/providers/github/services/organization/organization_repository_creation_limited/__init__.py b/prowler/providers/github/services/organization/organization_repository_creation_limited/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.metadata.json b/prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.metadata.json new file mode 100644 index 0000000000..9c83855af4 --- /dev/null +++ b/prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "github", + "CheckID": "organization_repository_creation_limited", + "CheckTitle": "Ensure repository creation is limited to trusted organization members.", + "CheckType": [], + "ServiceName": "organization", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "high", + "ResourceType": "GitHubOrganization", + "Description": "Ensure that repository creation is restricted so that only trusted owners or specific teams can create new repositories within the organization.", + "Risk": "Allowing all members to create repositories increases the likelihood of shadow repositories, data leakage, or malicious projects being introduced without oversight.", + "RelatedUrl": "https://docs.github.com/en/organizations/managing-organization-settings/restricting-repository-creation-in-your-organization", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Disable repository creation for members or limit it to specific trusted teams by adjusting Member privileges in the organization's settings.", + "Url": "https://docs.github.com/en/organizations/managing-organization-settings/restricting-repository-creation-in-your-organization" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.py b/prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.py new file mode 100644 index 0000000000..15e5b4b0aa --- /dev/null +++ b/prowler/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited.py @@ -0,0 +1,106 @@ +from typing import List + +from prowler.lib.check.models import Check, CheckReportGithub +from prowler.providers.github.services.organization.organization_client import ( + organization_client, +) + + +def _join_human_readable(items: List[str]) -> str: + """Return a simple human readable comma-separated list.""" + if not items: + return "" + if len(items) == 1: + return items[0] + return ", ".join(items[:-1]) + f" and {items[-1]}" + + +class organization_repository_creation_limited(Check): + """Check if repository creation is limited to trusted organization members.""" + + def execute(self) -> List[CheckReportGithub]: + findings = [] + for org in organization_client.organizations.values(): + repo_data = [ + getattr(org, "members_can_create_repositories", None), + getattr(org, "members_can_create_public_repositories", None), + getattr(org, "members_can_create_private_repositories", None), + getattr(org, "members_can_create_internal_repositories", None), + getattr(org, "members_allowed_repository_creation_type", None), + ] + + if all(value is None for value in repo_data): + continue + + report = CheckReportGithub(metadata=self.metadata(), resource=org) + + global_creation = getattr(org, "members_can_create_repositories", None) + public_creation = getattr( + org, "members_can_create_public_repositories", None + ) + private_creation = getattr( + org, "members_can_create_private_repositories", None + ) + internal_creation = getattr( + org, "members_can_create_internal_repositories", None + ) + creation_type = getattr( + org, "members_allowed_repository_creation_type", None + ) + + type_flags = [] + enabled_types = [] + + if global_creation is not None: + if global_creation: + enabled_types.append("repositories of any type") + else: + type_flags.append(False) + + visibility_flags = [ + (public_creation, "public repositories"), + (private_creation, "private repositories"), + (internal_creation, "internal repositories"), + ] + + for flag, label in visibility_flags: + if flag is not None: + type_flags.append(flag) + if flag: + enabled_types.append(label) + + if creation_type: + normalized_type = creation_type.lower() + if normalized_type == "none": + type_flags.append(False) + else: + creation_messages = { + "all": "repositories of any type", + "public": "public repositories", + "private": "private repositories", + "internal": "internal repositories", + "selected": "repositories for selected members or teams", + } + enabled_types.append( + creation_messages.get( + normalized_type, f"{creation_type} repositories" + ) + ) + + restricted = bool(type_flags) and all(flag is False for flag in type_flags) + + if restricted: + report.status = "PASS" + report.status_extended = f"Organization {org.name} has disabled repository creation for members." + else: + report.status = "FAIL" + unique_enabled = list(dict.fromkeys(enabled_types)) + allowed_desc = _join_human_readable(unique_enabled) + if allowed_desc: + report.status_extended = f"Organization {org.name} allows members to create {allowed_desc}." + else: + report.status_extended = f"Organization {org.name} does not have enough data to confirm repository creation restrictions." + + findings.append(report) + + return findings diff --git a/prowler/providers/github/services/organization/organization_service.py b/prowler/providers/github/services/organization/organization_service.py index 484ebcd378..2f7e9bc4ea 100644 --- a/prowler/providers/github/services/organization/organization_service.py +++ b/prowler/providers/github/services/organization/organization_service.py @@ -38,8 +38,9 @@ class Organization(GithubService): org_names_to_check = set() try: - for client in getattr(self, "clients", []) or []: - if getattr(self.provider, "organizations", None): + clients = getattr(self, "clients", []) + for client in clients: + if self.provider.organizations: org_names_to_check.update(self.provider.organizations) # If repositories are specified without organizations, don't perform organization checks @@ -147,22 +148,74 @@ class Organization(GithubService): logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + repo_creation_settings = { + "members_can_create_repositories": None, + "members_can_create_public_repositories": None, + "members_can_create_private_repositories": None, + "members_can_create_internal_repositories": None, + "members_allowed_repository_creation_type": None, + } - # Base permission (default repository permission for members) - base_perm: Optional[str] = None - try: - base_perm = getattr(org, "default_repository_permission", None) - except Exception as error: - logger.error( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) - base_perm = None + def _extract_flag(attribute: str, expected_type: type): + """Return attribute value if it matches expected type and is not a mock placeholder.""" + try: + value = getattr(org, attribute, None) + if hasattr(value, "_mock_parent"): + return None + if expected_type is bool and isinstance(value, bool): + return value + if expected_type is str and isinstance(value, str): + return value + return None + except Exception as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return None + + repo_creation_settings["members_can_create_repositories"] = _extract_flag( + "members_can_create_repositories", bool + ) + repo_creation_settings["members_can_create_public_repositories"] = ( + _extract_flag("members_can_create_public_repositories", bool) + ) + repo_creation_settings["members_can_create_private_repositories"] = ( + _extract_flag("members_can_create_private_repositories", bool) + ) + repo_creation_settings["members_can_create_internal_repositories"] = ( + _extract_flag("members_can_create_internal_repositories", bool) + ) + repo_creation_settings["members_allowed_repository_creation_type"] = ( + _extract_flag("members_allowed_repository_creation_type", str) + ) + + base_permission_raw = _extract_flag("default_repository_permission", str) + base_permission = ( + base_permission_raw.lower() + if isinstance(base_permission_raw, str) + else None + ) organizations[org.id] = Org( id=org.id, name=org.login, mfa_required=require_mfa, - base_permission=base_perm, + members_can_create_repositories=repo_creation_settings[ + "members_can_create_repositories" + ], + members_can_create_public_repositories=repo_creation_settings[ + "members_can_create_public_repositories" + ], + members_can_create_private_repositories=repo_creation_settings[ + "members_can_create_private_repositories" + ], + members_can_create_internal_repositories=repo_creation_settings[ + "members_can_create_internal_repositories" + ], + members_allowed_repository_creation_type=repo_creation_settings[ + "members_allowed_repository_creation_type" + ], + base_permission=base_permission, ) @@ -172,4 +225,9 @@ class Org(BaseModel): id: int name: str mfa_required: Optional[bool] = False + members_can_create_repositories: Optional[bool] = None + members_can_create_public_repositories: Optional[bool] = None + members_can_create_private_repositories: Optional[bool] = None + members_can_create_internal_repositories: Optional[bool] = None + members_allowed_repository_creation_type: Optional[str] = None base_permission: Optional[str] = None diff --git a/prowler/providers/iac/iac_provider.py b/prowler/providers/iac/iac_provider.py index 4e658c7849..15e9cda176 100644 --- a/prowler/providers/iac/iac_provider.py +++ b/prowler/providers/iac/iac_provider.py @@ -1,10 +1,11 @@ import json +import re import shutil import subprocess import sys import tempfile from os import environ -from typing import List +from typing import Generator, List from alive_progress import alive_bar from colorama import Fore, Style @@ -17,7 +18,7 @@ from prowler.config.config import ( from prowler.lib.check.models import CheckReportIAC from prowler.lib.logger import logger from prowler.lib.utils.utils import print_boxes -from prowler.providers.common.models import Audit_Metadata +from prowler.providers.common.models import Audit_Metadata, Connection from prowler.providers.common.provider import Provider @@ -173,7 +174,7 @@ class IacProvider(Provider): "Severity": finding["Severity"], "ResourceType": "iac", "Description": finding_description, - "Risk": "", + "Risk": "This provider has not defined a risk for this check.", "RelatedUrl": finding.get("PrimaryURL", ""), "Remediation": { "Code": { @@ -242,20 +243,39 @@ class IacProvider(Provider): logger.info( f"Cloning repository {original_url} into {temporary_directory}..." ) - with alive_bar( - ctrl_c=False, - bar="blocks", - spinner="classic", - stats=False, - enrich_print=False, - ) as bar: - try: - bar.title = f"-> Cloning {original_url}..." + + # Check if we're in an environment with a TTY + # Celery workers and other non-interactive environments don't have TTY + # and cannot use the alive_bar + try: + if sys.stdout.isatty(): + with alive_bar( + ctrl_c=False, + bar="blocks", + spinner="classic", + stats=False, + enrich_print=False, + ) as bar: + try: + bar.title = f"-> Cloning {original_url}..." + porcelain.clone( + repository_url, temporary_directory, depth=1 + ) + bar.title = "-> Repository cloned successfully!" + except Exception as clone_error: + bar.title = "-> Cloning failed!" + raise clone_error + else: + # No TTY, just clone without progress bar + logger.info(f"Cloning {original_url}...") porcelain.clone(repository_url, temporary_directory, depth=1) - bar.title = "-> Repository cloned successfully!" - except Exception as clone_error: - bar.title = "-> Cloning failed!" - raise clone_error + logger.info("Repository cloned successfully!") + except (AttributeError, OSError): + # Fallback if isatty() check fails + logger.info(f"Cloning {original_url}...") + porcelain.clone(repository_url, temporary_directory, depth=1) + logger.info("Repository cloned successfully!") + return temporary_directory except Exception as error: logger.critical( @@ -275,7 +295,10 @@ class IacProvider(Provider): scan_dir = self.scan_path try: - reports = self.run_scan(scan_dir, self.scanners, self.exclude_path) + # Collect all batches from the generator + reports = [] + for batch in self.run_scan(scan_dir, self.scanners, self.exclude_path): + reports.extend(batch) finally: if temp_dir: logger.info(f"Removing temporary directory {temp_dir}...") @@ -285,7 +308,7 @@ class IacProvider(Provider): def run_scan( self, directory: str, scanners: list[str], exclude_path: list[str] - ) -> List[CheckReportIAC]: + ) -> Generator[List[CheckReportIAC], None, None]: try: logger.info(f"Running IaC scan on {directory} ...") trivy_command = [ @@ -302,25 +325,47 @@ class IacProvider(Provider): ] if exclude_path: trivy_command.extend(["--skip-dirs", ",".join(exclude_path)]) - with alive_bar( - ctrl_c=False, - bar="blocks", - spinner="classic", - stats=False, - enrich_print=False, - ) as bar: - try: - bar.title = f"-> Running IaC scan on {directory} ..." - # Run Trivy with JSON output + + # Check if we're in an environment with a TTY + try: + if sys.stdout.isatty(): + with alive_bar( + ctrl_c=False, + bar="blocks", + spinner="classic", + stats=False, + enrich_print=False, + ) as bar: + try: + bar.title = f"-> Running IaC scan on {directory} ..." + # Run Trivy with JSON output + process = subprocess.run( + trivy_command, + capture_output=True, + text=True, + ) + bar.title = "-> Scan completed!" + except Exception as error: + bar.title = "-> Scan failed!" + raise error + else: + # No TTY, just run without progress bar + logger.info(f"Running Trivy scan on {directory}...") process = subprocess.run( trivy_command, capture_output=True, text=True, ) - bar.title = "-> Scan completed!" - except Exception as error: - bar.title = "-> Scan failed!" - raise error + logger.info("Trivy scan completed!") + except (AttributeError, OSError): + # Fallback if isatty() check fails + logger.info(f"Running Trivy scan on {directory}...") + process = subprocess.run( + trivy_command, + capture_output=True, + text=True, + ) + logger.info("Trivy scan completed!") # Log Trivy's stderr output with preserved log levels if process.stderr: for line in process.stderr.strip().split("\n"): @@ -354,14 +399,15 @@ class IacProvider(Provider): if not output: logger.warning("No findings returned from Trivy scan") - return [] + return except Exception as error: logger.critical( f"{error.__class__.__name__}:{error.__traceback__.tb_lineno} -- {error}" ) sys.exit(1) - reports = [] + batch = [] + batch_size = 100 # Process all trivy findings for finding in output: @@ -371,27 +417,44 @@ class IacProvider(Provider): report = self._process_finding( misconfiguration, finding["Target"], finding["Type"] ) - reports.append(report) + batch.append(report) + if len(batch) >= batch_size: + yield batch + batch = [] + # Process Vulnerabilities for vulnerability in finding.get("Vulnerabilities", []): report = self._process_finding( vulnerability, finding["Target"], finding["Type"] ) - reports.append(report) + batch.append(report) + if len(batch) >= batch_size: + yield batch + batch = [] + # Process Secrets for secret in finding.get("Secrets", []): report = self._process_finding( secret, finding["Target"], finding["Class"] ) - reports.append(report) + batch.append(report) + if len(batch) >= batch_size: + yield batch + batch = [] + # Process Licenses for license in finding.get("Licenses", []): report = self._process_finding( license, finding["Target"], finding["Type"] ) - reports.append(report) + batch.append(report) + if len(batch) >= batch_size: + yield batch + batch = [] - return reports + # Yield any remaining findings in the last batch + if batch: + yield batch except Exception as error: if "No such file or directory: 'trivy'" in str(error): @@ -434,3 +497,95 @@ class IacProvider(Provider): ) print_boxes(report_lines, report_title) + + @staticmethod + def test_connection( + scan_repository_url: str = None, + oauth_app_token: str = None, + access_token: str = None, + raise_on_exception: bool = True, + provider_id: str = None, + ) -> "Connection": + """Test connection to IaC repository. + + Test the connection to the IaC repository using the provided credentials. + + Args: + scan_repository_url (str): Repository URL to scan. + oauth_app_token (str): OAuth App token for authentication. + access_token (str): Access token for authentication (alias for oauth_app_token). + raise_on_exception (bool): Flag indicating whether to raise an exception if the connection fails. + provider_id (str): The provider ID, in this case it's the repository URL. + + Returns: + Connection: Connection object with success status or error information. + + Raises: + Exception: If failed to test the connection to the repository. + + Examples: + >>> IacProvider.test_connection(scan_repository_url="https://github.com/user/repo") + Connection(is_connected=True) + """ + try: + # If provider_id is provided and scan_repository_url is not, use provider_id as the repository URL + if provider_id and not scan_repository_url: + scan_repository_url = provider_id + + # Handle both oauth_app_token and access_token parameters + if access_token and not oauth_app_token: + oauth_app_token = access_token + + if not scan_repository_url: + return Connection( + is_connected=False, error="Repository URL is required" + ) + + # Try to clone the repository to test the connection + with tempfile.TemporaryDirectory(): + try: + if oauth_app_token: + # If token is provided, use it for authentication + # Extract the domain and path from the URL + url_pattern = r"(https?://)([^/]+)/(.+)" + match = re.match(url_pattern, scan_repository_url) + if match: + protocol, domain, path = match.groups() + # Construct URL with token + auth_url = f"{protocol}x-access-token:{oauth_app_token}@{domain}/{path}" + else: + auth_url = scan_repository_url + else: + # Public repository + auth_url = scan_repository_url + + # Use dulwich to test the connection + porcelain.ls_remote(auth_url) + + return Connection(is_connected=True) + + except Exception as e: + error_msg = str(e) + if "authentication" in error_msg.lower() or "401" in error_msg: + return Connection( + is_connected=False, + error="Authentication failed. Please check your access token.", + ) + elif "404" in error_msg or "not found" in error_msg.lower(): + return Connection( + is_connected=False, + error="Repository not found or not accessible.", + ) + else: + return Connection( + is_connected=False, + error=f"Failed to connect to repository: {error_msg}", + ) + + except Exception as error: + if raise_on_exception: + raise + return Connection( + is_connected=False, + error=f"Unexpected error testing connection: {str(error)}", + ) diff --git a/prowler/providers/mongodbatlas/mongodbatlas_provider.py b/prowler/providers/mongodbatlas/mongodbatlas_provider.py index 82e48eadff..b379e4ab9f 100644 --- a/prowler/providers/mongodbatlas/mongodbatlas_provider.py +++ b/prowler/providers/mongodbatlas/mongodbatlas_provider.py @@ -54,6 +54,7 @@ class MongodbatlasProvider(Provider): mutelist_content: dict = None, # Optional filters atlas_project_id: str = None, + atlas_organization_id: str = None, ): """ MongoDB Atlas Provider constructor @@ -67,6 +68,7 @@ class MongodbatlasProvider(Provider): mutelist_path: Path to the mutelist file mutelist_content: Mutelist content atlas_project_id: Project ID to filter + atlas_organization_id: Organization ID """ logger.info("Instantiating MongoDB Atlas Provider...") @@ -79,6 +81,7 @@ class MongodbatlasProvider(Provider): # Store filter options self._project_id = atlas_project_id + self._organization_id = atlas_organization_id # Audit Config if config_content: @@ -292,6 +295,7 @@ class MongodbatlasProvider(Provider): atlas_public_key: str = "", atlas_private_key: str = "", raise_on_exception: bool = True, + provider_id: str = None, ) -> Connection: """ Test connection to MongoDB Atlas @@ -300,7 +304,7 @@ class MongodbatlasProvider(Provider): atlas_public_key: MongoDB Atlas API public key atlas_private_key: MongoDB Atlas API private key raise_on_exception: Whether to raise exceptions - + provider_id: MongoDB Atlas project ID to validate access (added for API compatibility) Returns: Connection: Connection status """ diff --git a/prowler/providers/oraclecloud/lib/arguments/arguments.py b/prowler/providers/oraclecloud/lib/arguments/arguments.py index bdbd6b7642..66971d0a58 100644 --- a/prowler/providers/oraclecloud/lib/arguments/arguments.py +++ b/prowler/providers/oraclecloud/lib/arguments/arguments.py @@ -5,9 +5,11 @@ from prowler.providers.oraclecloud.config import OCI_DEFAULT_CONFIG_FILE, OCI_RE def init_parser(self): - """Init the OCI Provider CLI parser""" + """Init the Oracle Cloud Infrastructure Provider CLI parser""" oci_parser = self.subparsers.add_parser( - "oci", parents=[self.common_providers_parser], help="OCI Provider" + "oraclecloud", + parents=[self.common_providers_parser], + help="Oracle Cloud Infrastructure Provider", ) # Config File Authentication Options @@ -109,15 +111,4 @@ def validate_arguments(arguments: Namespace) -> tuple[bool, str]: "Cannot use --use-instance-principal with --oci-config-file or --profile options", ) - # # Validate compartment OCIDs if provided - # if arguments.compartment_id: - # for compartment_id in arguments.compartment_id: - # if not OciProvider.validate_ocid(compartment_id, "compartment"): - # # Check if it's a tenancy OCID (root compartment) - # if not OciProvider.validate_ocid(compartment_id, "tenancy"): - # return ( - # False, - # f"Invalid compartment OCID: {compartment_id}", - # ) - return (True, "") diff --git a/prowler/providers/oraclecloud/lib/service/service.py b/prowler/providers/oraclecloud/lib/service/service.py index 7007eba384..971c1fe31f 100644 --- a/prowler/providers/oraclecloud/lib/service/service.py +++ b/prowler/providers/oraclecloud/lib/service/service.py @@ -1,7 +1,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed from prowler.lib.logger import logger -from prowler.providers.oraclecloud.oci_provider import OciProvider +from prowler.providers.oraclecloud.oraclecloud_provider import OraclecloudProvider MAX_WORKERS = 10 @@ -16,13 +16,13 @@ class OCIService: - Handles compartment traversal """ - def __init__(self, service: str, provider: OciProvider): + def __init__(self, service: str, provider: OraclecloudProvider): """ Initialize the OCIService base class. Args: service (str): The OCI service name (e.g., 'compute', 'object_storage'). - provider (OciProvider): The OCI provider instance. + provider (OraclecloudProvider): The Oracle Cloud Infrastructure provider instance. """ # Audit Information self.provider = provider diff --git a/prowler/providers/oraclecloud/oci_provider.py b/prowler/providers/oraclecloud/oraclecloud_provider.py similarity index 97% rename from prowler/providers/oraclecloud/oci_provider.py rename to prowler/providers/oraclecloud/oraclecloud_provider.py index 5735415386..08d654d580 100644 --- a/prowler/providers/oraclecloud/oci_provider.py +++ b/prowler/providers/oraclecloud/oraclecloud_provider.py @@ -40,9 +40,9 @@ from prowler.providers.oraclecloud.models import ( ) -class OciProvider(Provider): +class OraclecloudProvider(Provider): """ - OciProvider class is the main class for the OCI provider. + OraclecloudProvider class is the main class for the Oracle Cloud Infrastructure provider. This class is responsible for initializing the OCI provider, setting up the OCI session, validating the OCI credentials, getting the OCI identity, and managing compartments and regions. @@ -58,7 +58,7 @@ class OciProvider(Provider): audit_metadata (Audit_Metadata): The audit metadata. """ - _type: str = "oci" + _type: str = "oraclecloud" _identity: OCIIdentityInfo _session: OCISession _audit_config: dict @@ -118,11 +118,11 @@ class OciProvider(Provider): or - export OCI_CLI_AUTH=instance_principal (for instance principal) - To create a new OCI provider object: - - oci = OciProvider() - - oci = OciProvider(profile="profile_name") - - oci = OciProvider(oci_config_file="/path/to/config") - - oci = OciProvider(use_instance_principal=True) - - oci = OciProvider(user="ocid1...", fingerprint="...", key_content="...", tenancy="ocid1...", region="us-ashburn-1") + - oci = OraclecloudProvider() + - oci = OraclecloudProvider(profile="profile_name") + - oci = OraclecloudProvider(oci_config_file="/path/to/config") + - oci = OraclecloudProvider(use_instance_principal=True) + - oci = OraclecloudProvider(user="ocid1...", fingerprint="...", key_content="...", tenancy="ocid1...", region="us-ashburn-1") """ logger.info("Initializing OCI provider ...") @@ -439,7 +439,7 @@ class OciProvider(Provider): ) # Validate tenancy OCID format - if not OciProvider.validate_ocid(tenancy_id, "tenancy"): + if not OraclecloudProvider.validate_ocid(tenancy_id, "tenancy"): raise OCIInvalidTenancyError( file=pathlib.Path(__file__).name, message=f"Invalid tenancy OCID format: {tenancy_id}", @@ -817,11 +817,11 @@ class OciProvider(Provider): Exception: If there is an unexpected error. Examples: - >>> OciProvider.test_connection(profile="DEFAULT", raise_on_exception=False) + >>> OraclecloudProvider.test_connection(profile="DEFAULT", raise_on_exception=False) Connection(is_connected=True, Error=None) - >>> OciProvider.test_connection(use_instance_principal=True, raise_on_exception=False) + >>> OraclecloudProvider.test_connection(use_instance_principal=True, raise_on_exception=False) Connection(is_connected=True, Error=None) - >>> OciProvider.test_connection( + >>> OraclecloudProvider.test_connection( user="ocid1.user.oc1..aaaaaa...", fingerprint="12:34:56:78:...", key_content="base64_encoded_key", @@ -890,13 +890,13 @@ class OciProvider(Provider): session = OCISession(config=config, signer=None, profile=None) else: # Use traditional config file or instance principal authentication - session = OciProvider.setup_session( + session = OraclecloudProvider.setup_session( oci_config_file=oci_config_file, profile=profile, use_instance_principal=use_instance_principal, ) - identity = OciProvider.set_identity( + identity = OraclecloudProvider.set_identity( session=session, region=region, ) @@ -1032,7 +1032,7 @@ class OciProvider(Provider): set: A set of region names. Example: - >>> OciProvider.get_regions() + >>> OraclecloudProvider.get_regions() {"us-ashburn-1", "us-phoenix-1", ...} """ return set(OCI_REGIONS.keys()) diff --git a/prowler/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted.metadata.json b/prowler/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted.metadata.json index e456efe559..b5d7bcc6ae 100644 --- a/prowler/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted.metadata.json +++ b/prowler/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted.metadata.json @@ -1,34 +1,38 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "analytics_instance_access_restricted", - "CheckTitle": "Ensure Oracle Analytics Cloud (OAC) access is restricted to allowed sources or deployed within a Virtual Cloud Network", - "CheckType": [ - "Software and Configuration Checks", - "Industry and Regulatory Standards", - "CIS OCI Foundations Benchmark" - ], + "CheckTitle": "Oracle Analytics Cloud instance is deployed within a Virtual Cloud Network or restricts public access to allowed sources", + "CheckType": [], "ServiceName": "analytics", "SubServiceName": "", - "ResourceIdTemplate": "oci:analytics:instance", + "ResourceIdTemplate": "", "Severity": "high", "ResourceType": "AnalyticsInstance", - "Description": "Oracle Analytics Cloud access should be restricted or deployed in VCN.", - "Risk": "Not meeting this network security requirement increases risk of unauthorized access.", - "RelatedUrl": "https://docs.oracle.com/en-us/iaas/Content/Network/home.htm", + "Description": "Oracle Analytics Cloud endpoints are evaluated for **network exposure**. Public endpoints must use **restricted allowlists** of specific IPs/CIDRs; presence of `0.0.0.0/0` or no allowed sources indicates unrestricted access. Instances using a **VCN/private endpoint** or public endpoints limited to specific sources align with the intended exposure model.", + "Risk": "Unrestricted OAC endpoints allow Internet-wide access to the login surface, enabling **credential stuffing** and **brute force**. Account takeover can expose **reports and data sources** (**confidentiality**), permit **dashboard/model changes** (**integrity**), and support **lateral movement** into connected systems.", + "RelatedUrl": "", + "AdditionalURLs": [ + "https://docs.public.content.oci.oraclecloud.com/en-us/iaas/analytics-cloud/doc/public-endpoints-and-access-control-rules.html", + "https://docs.oracle.com/en/cloud/paas/analytics-cloud/acsds/connect-databases-deployed-public-ip-address.html", + "https://docs.oracle.com/en/cloud/paas/analytics-cloud/acoci/top-faqs-public-or-private-endpoint-security.html", + "https://docs.oracle.com/en/cloud/paas/analytics-cloud/acoci/manage-ingress-access-rules-public-endpoint-using-console.html", + "https://docs.oracle.com/en-us/iaas/analytics-cloud/doc/public-endpoints-and-access-control-rules.html" + ], "Remediation": { "Code": { "CLI": "", "NativeIaC": "", - "Other": "", - "Terraform": "" + "Other": "1. In OCI Console, go to Analytics & AI > Analytics Cloud and select your instance\n2. On Instance Details, under Network Access, click Edit next to Access Control\n3. Remove any 0.0.0.0/0 entry (if present)\n4. Add an access rule with the specific allowed public IP or CIDR\n5. Click Save", + "Terraform": "```hcl\nresource \"oci_analytics_analytics_instance\" \"example\" {\n compartment_id = \"\"\n name = \"\"\n feature_set = \"ENTERPRISE_ANALYTICS\"\n license_type = \"LICENSE_INCLUDED\"\n idcs_access_token = \"\"\n\n capacity {\n capacity_type = \"OLPU_COUNT\"\n capacity_value = 1\n }\n\n network_endpoint_details {\n network_endpoint_type = \"PUBLIC\"\n whitelisted_ips = [\"\"] # Critical: restrict to specific allowed CIDR; not 0.0.0.0/0\n }\n}\n```" }, "Recommendation": { - "Text": "Ensure Oracle Analytics Cloud (OAC) access is restricted to allowed sources or deployed within a Virtual Cloud Network", - "Url": "https://hub.prowler.com/check/oci/analytics_instance_access_restricted" + "Text": "Prefer **private deployment in a VCN** and apply **least privilege** network access. *If public is required*, enforce **allowlists** to specific IPs/CIDRs and never include `0.0.0.0/0`. Use **private access channels/service gateways**, require **MFA/SSO**, and apply **defense in depth** (WAF, audit monitoring) to reduce exposure.", + "Url": "https://hub.prowler.com/check/analytics_instance_access_restricted" } }, "Categories": [ - "network-security" + "internet-exposed", + "trust-boundaries" ], "DependsOn": [], "RelatedTo": [], diff --git a/prowler/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days.metadata.json b/prowler/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days.metadata.json index 9089dff880..c31bcbdd02 100644 --- a/prowler/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days.metadata.json +++ b/prowler/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "audit_log_retention_period_365_days", "CheckTitle": "Ensure audit log retention period is set to 365 days or greater", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk.metadata.json b/prowler/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk.metadata.json index bfde317c9d..741f9f731c 100644 --- a/prowler/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk.metadata.json +++ b/prowler/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "blockstorage_block_volume_encrypted_with_cmk", "CheckTitle": "Ensure Block Volumes are encrypted with Customer Managed Keys", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk.metadata.json b/prowler/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk.metadata.json index 553b9c6ae0..638ce51d01 100644 --- a/prowler/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk.metadata.json +++ b/prowler/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "blockstorage_boot_volume_encrypted_with_cmk", "CheckTitle": "Ensure Boot Volumes are encrypted with Customer Managed Key", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled.metadata.json b/prowler/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled.metadata.json index 09a09d3f1e..7e0722f9a1 100644 --- a/prowler/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "cloudguard_enabled", "CheckTitle": "Ensure Cloud Guard is enabled in the root compartment of the tenancy", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled.metadata.json b/prowler/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled.metadata.json index 06af08544e..cd6d9302e0 100644 --- a/prowler/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "compute_instance_in_transit_encryption_enabled", "CheckTitle": "Ensure In-transit Encryption is enabled on Compute Instance", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled.metadata.json b/prowler/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled.metadata.json index 58162d2587..c2a525e0ad 100644 --- a/prowler/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled.metadata.json +++ b/prowler/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "compute_instance_legacy_metadata_endpoint_disabled", "CheckTitle": "Ensure Compute Instance Legacy Metadata service endpoint is disabled", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled.metadata.json b/prowler/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled.metadata.json index 1ecdf4de16..ef459a15f8 100644 --- a/prowler/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "compute_instance_secure_boot_enabled", "CheckTitle": "Ensure Secure Boot is enabled on Compute Instance", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted.metadata.json b/prowler/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted.metadata.json index ced824cc2a..f2fd7a600f 100644 --- a/prowler/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted.metadata.json +++ b/prowler/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "database_autonomous_database_access_restricted", "CheckTitle": "Ensure Oracle Autonomous Shared Database (ADB) access is restricted or deployed within a VCN", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists.metadata.json b/prowler/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists.metadata.json index d07852ddd7..aeea44d734 100644 --- a/prowler/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_notification_topic_and_subscription_exists", "CheckTitle": "Create at least one notification topic and subscription to receive monitoring alerts", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems.metadata.json index db5abd08e7..17285acece 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_cloudguard_problems", "CheckTitle": "Ensure a notification is configured for Oracle Cloud Guard problems detected", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes.metadata.json index a871956a9d..16840d2477 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_iam_group_changes", "CheckTitle": "Ensure a notification is configured for IAM group changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes.metadata.json index 05b9553b7d..b2251abce9 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_iam_policy_changes", "CheckTitle": "Ensure a notification is configured for IAM policy changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes.metadata.json index e23e26f18e..b5cbf2990d 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_identity_provider_changes", "CheckTitle": "Ensure a notification is configured for Identity Provider changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes.metadata.json index ffe8b65901..4869f2330a 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_idp_group_mapping_changes", "CheckTitle": "Ensure a notification is configured for IdP group mapping changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication.metadata.json index 6a022932ac..4225e5c028 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_local_user_authentication", "CheckTitle": "Ensure a notification is configured for Local OCI User Authentication", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes.metadata.json index 11433e77f9..bb3461a66c 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_network_gateway_changes", "CheckTitle": "Ensure a notification is configured for changes to network gateways", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes.metadata.json index 6fba97f5c1..abf62a726f 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_network_security_group_changes", "CheckTitle": "Ensure a notification is configured for network security group changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes.metadata.json index 8653611cf4..aa5f454e5c 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_route_table_changes", "CheckTitle": "Ensure a notification is configured for changes to route tables", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes.metadata.json index f7e944d0fd..2a35524632 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_security_list_changes", "CheckTitle": "Ensure a notification is configured for security list changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes.metadata.json index a0e23329e3..206dfd0136 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_user_changes", "CheckTitle": "Ensure a notification is configured for user changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes.metadata.json b/prowler/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes.metadata.json index 29d311d283..cf3c71a379 100644 --- a/prowler/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes.metadata.json +++ b/prowler/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "events_rule_vcn_changes", "CheckTitle": "Ensure a notification is configured for VCN changes", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk.metadata.json b/prowler/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk.metadata.json index 9fd7be5782..41848707ba 100644 --- a/prowler/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk.metadata.json +++ b/prowler/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "filestorage_file_system_encrypted_with_cmk", "CheckTitle": "Ensure File Storage Systems are encrypted with Customer Managed Keys", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins.metadata.json index 4e196d701c..9d4ec0bf26 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_iam_admins_cannot_update_tenancy_admins", "CheckTitle": "Ensure IAM administrators cannot update tenancy Administrators group", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used.metadata.json index 8e79ed8f9e..8c7e03d5c7 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_instance_principal_used", "CheckTitle": "Ensure Instance Principal authentication is used for OCI instances, OCI Cloud Databases and OCI Functions to access OCI resources", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment.metadata.json index bcfd9b6a7a..510e4ddaf8 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_no_resources_in_root_compartment", "CheckTitle": "Ensure no resources are created in the root compartment", "CheckType": [], diff --git a/prowler/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists.metadata.json index b8dad7067d..41e0714daf 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_non_root_compartment_exists", "CheckTitle": "Create at least one non-root compartment in your tenancy to store cloud resources", "CheckType": [], diff --git a/prowler/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days.metadata.json index 13837295e8..ae4f3f810f 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_password_policy_expires_within_365_days", "CheckTitle": "Ensure IAM password policy expires passwords within 365 days", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14.metadata.json index f8e75d073a..b279d9e162 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_password_policy_minimum_length_14", "CheckTitle": "Ensure IAM password policy requires minimum length of 14 or greater", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse.metadata.json index 66d0fd9e42..552e8e8608 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_password_policy_prevents_reuse", "CheckTitle": "Ensure IAM password policy prevents password reuse", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist.metadata.json index 8c39459df8..156307f269 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_service_level_admins_exist", "CheckTitle": "Ensure service level admins are created to manage resources of particular service", "CheckType": [], diff --git a/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited.metadata.json index 0e78b3d72b..48e008db1f 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_tenancy_admin_permissions_limited", "CheckTitle": "Ensure permissions on all resources are given only to the tenancy administrator group", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys.metadata.json index cf915adba5..daa831f862 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_tenancy_admin_users_no_api_keys", "CheckTitle": "Ensure API keys are not created for tenancy administrator users", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days.metadata.json index 30d6354fcd..0621d213af 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_user_api_keys_rotated_90_days", "CheckTitle": "Ensure user API keys rotate within 90 days or less", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days.metadata.json index 2863fa21fb..f0f170f1db 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_user_auth_tokens_rotated_90_days", "CheckTitle": "Ensure user auth tokens rotate within 90 days or less", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days.metadata.json index bc98570d89..9d6da4c7b5 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_user_customer_secret_keys_rotated_90_days", "CheckTitle": "Ensure user customer secret keys rotate within 90 days or less", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days.metadata.json index 8f0e103a4d..0aa3e5d12c 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_user_db_passwords_rotated_90_days", "CheckTitle": "Ensure user IAM Database Passwords rotate within 90 days", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access.metadata.json index cd3bf404b4..283fe65412 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_user_mfa_enabled_console_access", "CheckTitle": "Ensure MFA is enabled for all users with a console password", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address.metadata.json b/prowler/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address.metadata.json index 73dd2e309e..c1af4c37b2 100644 --- a/prowler/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address.metadata.json +++ b/prowler/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "identity_user_valid_email_address", "CheckTitle": "Ensure all OCI IAM user accounts have a valid and current email address", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted.metadata.json b/prowler/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted.metadata.json index f73a4625a8..20673e5f60 100644 --- a/prowler/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted.metadata.json +++ b/prowler/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "integration_instance_access_restricted", "CheckTitle": "Ensure Oracle Integration Cloud (OIC) access is restricted to allowed sources", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled.metadata.json b/prowler/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled.metadata.json index 036d889011..2c6cfe47a8 100644 --- a/prowler/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "kms_key_rotation_enabled", "CheckTitle": "Ensure customer created Customer Managed Key (CMK) is rotated at least annually", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic.metadata.json b/prowler/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic.metadata.json index 71a2e69c2b..b7c43eedc3 100644 --- a/prowler/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic.metadata.json +++ b/prowler/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "network_default_security_list_restricts_traffic", "CheckTitle": "Ensure the default security list of every VCN restricts all traffic except ICMP", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port.metadata.json b/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port.metadata.json index 0b0016c0f7..b95bd0db6a 100644 --- a/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port.metadata.json +++ b/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "network_security_group_ingress_from_internet_to_rdp_port", "CheckTitle": "Ensure no network security groups allow ingress from 0.0.0.0/0 to port 3389", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port.metadata.json b/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port.metadata.json index 05068d7c3b..b64e1ad5a1 100644 --- a/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port.metadata.json +++ b/prowler/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "network_security_group_ingress_from_internet_to_ssh_port", "CheckTitle": "Ensure no network security groups allow ingress from 0.0.0.0/0 to port 22", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port.metadata.json b/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port.metadata.json index f6a8650a97..064a1a9986 100644 --- a/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port.metadata.json +++ b/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "network_security_list_ingress_from_internet_to_rdp_port", "CheckTitle": "Ensure no security lists allow ingress from 0.0.0.0/0 to port 3389", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port.metadata.json b/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port.metadata.json index b380635a94..c94d6d85c5 100644 --- a/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port.metadata.json +++ b/prowler/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "network_security_list_ingress_from_internet_to_ssh_port", "CheckTitle": "Ensure no security lists allow ingress from 0.0.0.0/0 to port 22", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled.metadata.json b/prowler/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled.metadata.json index 4fa542a15c..7abd9c44be 100644 --- a/prowler/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "network_vcn_subnet_flow_logs_enabled", "CheckTitle": "Ensure VCN flow logging is enabled for all subnets", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk.metadata.json b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk.metadata.json index f01fd3e4bf..2f58776f38 100644 --- a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk.metadata.json +++ b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "objectstorage_bucket_encrypted_with_cmk", "CheckTitle": "Ensure Object Storage Buckets are encrypted with a Customer Managed Key (CMK)", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled.metadata.json b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled.metadata.json index 94ebcd4be3..73f77bcdce 100644 --- a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "objectstorage_bucket_logging_enabled", "CheckTitle": "Ensure write level Object Storage logging is enabled for all buckets", "CheckType": [], diff --git a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible.metadata.json b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible.metadata.json index 2d9b38be45..433cc3b4a2 100644 --- a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible.metadata.json +++ b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "objectstorage_bucket_not_publicly_accessible", "CheckTitle": "Ensure no Object Storage buckets are publicly visible", "CheckType": [ diff --git a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled.metadata.json b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled.metadata.json index 3ec7217d16..72df7b3e29 100644 --- a/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled.metadata.json +++ b/prowler/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled.metadata.json @@ -1,5 +1,5 @@ { - "Provider": "oci", + "Provider": "oraclecloud", "CheckID": "objectstorage_bucket_versioning_enabled", "CheckTitle": "Ensure Versioning is Enabled for Object Storage Buckets", "CheckType": [ diff --git a/tests/lib/check/check_loader_test.py b/tests/lib/check/check_loader_test.py index 12e9b3e547..740ed67844 100644 --- a/tests/lib/check/check_loader_test.py +++ b/tests/lib/check/check_loader_test.py @@ -1,3 +1,4 @@ +import pytest from mock import patch from prowler.lib.check.checks_loader import ( @@ -190,18 +191,22 @@ class TestCheckLoader: def test_load_checks_to_execute_with_severities_and_services_not_within_severity( self, ): + """Test that service not in metadata causes sys.exit(1) when used with severities""" bulk_checks_metatada = { S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() } service_list = ["ec2"] severities = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY] - assert set() == load_checks_to_execute( - bulk_checks_metadata=bulk_checks_metatada, - service_list=service_list, - severities=severities, - provider=self.provider, - ) + # ec2 service doesn't exist in the metadata, so it should exit with error + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + service_list=service_list, + severities=severities, + provider=self.provider, + ) + assert exc_info.value.code == 1 def test_load_checks_to_execute_with_checks_file( self, @@ -382,3 +387,140 @@ class TestCheckLoader: categories=categories, provider=self.provider, ) + + def test_load_checks_to_execute_with_invalid_check(self): + """Test that invalid check names cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + check_list = ["invalid_check_name"] + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + check_list=check_list, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_multiple_invalid_checks(self): + """Test that multiple invalid check names cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + check_list = ["invalid_check_1", "invalid_check_2", "invalid_check_3"] + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + check_list=check_list, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_mixed_valid_invalid_checks(self): + """Test that mix of valid and invalid checks cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + check_list = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME, "invalid_check"] + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + check_list=check_list, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_invalid_service(self): + """Test that invalid service names cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + service_list = ["invalid_service"] + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + service_list=service_list, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_invalid_service_and_severity(self): + """Test that invalid service names with severity cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + service_list = ["invalid_service"] + severities = [S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_SEVERITY] + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + service_list=service_list, + severities=severities, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_multiple_invalid_services(self): + """Test that multiple invalid service names cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + service_list = ["invalid_service_1", "invalid_service_2"] + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + service_list=service_list, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_invalid_category(self): + """Test that invalid category names cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + categories = {"invalid_category"} + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + categories=categories, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_multiple_invalid_categories(self): + """Test that multiple invalid category names cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + categories = {"invalid_category_1", "invalid_category_2"} + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + categories=categories, + provider=self.provider, + ) + assert exc_info.value.code == 1 + + def test_load_checks_to_execute_with_mixed_valid_invalid_categories(self): + """Test that mix of valid and invalid categories cause sys.exit(1)""" + bulk_checks_metatada = { + S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata() + } + categories = {"internet-exposed", "invalid_category"} + + with pytest.raises(SystemExit) as exc_info: + load_checks_to_execute( + bulk_checks_metadata=bulk_checks_metatada, + categories=categories, + provider=self.provider, + ) + assert exc_info.value.code == 1 diff --git a/tests/lib/cli/parser_test.py b/tests/lib/cli/parser_test.py index 9d04e050d1..c645a7b128 100644 --- a/tests/lib/cli/parser_test.py +++ b/tests/lib/cli/parser_test.py @@ -17,7 +17,7 @@ prowler_command = "prowler" # capsys # https://docs.pytest.org/en/7.1.x/how-to/capture-stdout-stderr.html -prowler_default_usage_error = "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,github,nhn,mongodbatlas,oci,dashboard,iac} ..." +prowler_default_usage_error = "usage: prowler [-h] [--version] {aws,azure,gcp,kubernetes,m365,github,nhn,mongodbatlas,oraclecloud,dashboard,iac} ..." def mock_get_available_providers(): @@ -31,7 +31,7 @@ def mock_get_available_providers(): "iac", "nhn", "mongodbatlas", - "oci", + "oraclecloud", ] diff --git a/tests/lib/outputs/compliance/ens/ens_aws_test.py b/tests/lib/outputs/compliance/ens/ens_aws_test.py index 9252b6d8c0..97d45c74c6 100644 --- a/tests/lib/outputs/compliance/ens/ens_aws_test.py +++ b/tests/lib/outputs/compliance/ens/ens_aws_test.py @@ -135,5 +135,5 @@ class TestAWSENS: mock_file.seek(0) content = mock_file.read() - expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;FRAMEWORK;NAME\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;eu-west-1;{datetime.now()};op.exp.8.aws.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;service_test_check_id;False;;ENS;ENS RD 311/2022\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.aws.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check;ENS;ENS RD 311/2022\r\n" + expected_csv = f"PROVIDER;DESCRIPTION;ACCOUNTID;REGION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;FRAMEWORK;NAME\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;eu-west-1;{datetime.now()};op.exp.8.aws.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;service_test_check_id;False;;ENS;ENS RD 311/2022 - Categoría Alta\r\naws;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.aws.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check;ENS;ENS RD 311/2022 - Categoría Alta\r\n" assert content == expected_csv diff --git a/tests/lib/outputs/compliance/ens/ens_azure_test.py b/tests/lib/outputs/compliance/ens/ens_azure_test.py index 8923f45547..50538976da 100644 --- a/tests/lib/outputs/compliance/ens/ens_azure_test.py +++ b/tests/lib/outputs/compliance/ens/ens_azure_test.py @@ -144,6 +144,6 @@ class TestAzureENS: mock_file.seek(0) content = mock_file.read() - expected_csv = f"PROVIDER;DESCRIPTION;SUBSCRIPTIONID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;FRAMEWORK;NAME\r\nazure;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;global;{datetime.now()};op.exp.8.azure.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;service_test_check_id;False;;ENS;ENS RD 311/2022\r\nazure;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.azure.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check;ENS;ENS RD 311/2022\r\n" + expected_csv = f"PROVIDER;DESCRIPTION;SUBSCRIPTIONID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;FRAMEWORK;NAME\r\nazure;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;global;{datetime.now()};op.exp.8.azure.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;service_test_check_id;False;;ENS;ENS RD 311/2022 - Categoría Alta\r\nazure;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.azure.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check;ENS;ENS RD 311/2022 - Categoría Alta\r\n" assert content == expected_csv diff --git a/tests/lib/outputs/compliance/ens/ens_gcp_test.py b/tests/lib/outputs/compliance/ens/ens_gcp_test.py index afdbcdb3b0..eacc21c3ae 100644 --- a/tests/lib/outputs/compliance/ens/ens_gcp_test.py +++ b/tests/lib/outputs/compliance/ens/ens_gcp_test.py @@ -144,6 +144,6 @@ class TestGCPENS: mock_file.seek(0) content = mock_file.read() - expected_csv = f"PROVIDER;DESCRIPTION;PROJECTID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;FRAMEWORK;NAME\r\ngcp;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;global;{datetime.now()};op.exp.8.gcp.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;service_test_check_id;False;;ENS;ENS RD 311/2022\r\ngcp;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.gcp.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check;ENS;ENS RD 311/2022\r\n" + expected_csv = f"PROVIDER;DESCRIPTION;PROJECTID;LOCATION;ASSESSMENTDATE;REQUIREMENTS_ID;REQUIREMENTS_DESCRIPTION;REQUIREMENTS_ATTRIBUTES_IDGRUPOCONTROL;REQUIREMENTS_ATTRIBUTES_MARCO;REQUIREMENTS_ATTRIBUTES_CATEGORIA;REQUIREMENTS_ATTRIBUTES_DESCRIPCIONCONTROL;REQUIREMENTS_ATTRIBUTES_NIVEL;REQUIREMENTS_ATTRIBUTES_TIPO;REQUIREMENTS_ATTRIBUTES_DIMENSIONES;REQUIREMENTS_ATTRIBUTES_MODOEJECUCION;REQUIREMENTS_ATTRIBUTES_DEPENDENCIAS;STATUS;STATUSEXTENDED;RESOURCEID;CHECKID;MUTED;RESOURCENAME;FRAMEWORK;NAME\r\ngcp;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;123456789012;global;{datetime.now()};op.exp.8.gcp.ct.3;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;PASS;;;service_test_check_id;False;;ENS;ENS RD 311/2022 - Categoría Alta\r\ngcp;The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.;;;{datetime.now()};op.exp.8.gcp.ct.4;Registro de actividad;op.exp.8;operacional;explotación;Habilitar la validación de archivos en todos los trails, evitando así que estos se vean modificados o eliminados.;alto;requisito;trazabilidad;automático;;MANUAL;Manual check;manual_check;manual;False;Manual check;ENS;ENS RD 311/2022 - Categoría Alta\r\n" assert content == expected_csv diff --git a/tests/lib/outputs/compliance/fixtures.py b/tests/lib/outputs/compliance/fixtures.py index caba697417..7b29411663 100644 --- a/tests/lib/outputs/compliance/fixtures.py +++ b/tests/lib/outputs/compliance/fixtures.py @@ -490,7 +490,7 @@ MITRE_ATTACK_GCP = Compliance( ENS_RD2022_AWS = Compliance( Framework="ENS", - Name="ENS RD 311/2022", + Name="ENS RD 311/2022 - Categoría Alta", Provider="AWS", Version="RD2022", Description="The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", @@ -538,7 +538,7 @@ ENS_RD2022_AWS = Compliance( ENS_RD2022_AZURE = Compliance( Framework="ENS", - Name="ENS RD 311/2022", + Name="ENS RD 311/2022 - Categoría Alta", Provider="Azure", Version="RD2022", Description="The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", @@ -585,7 +585,7 @@ ENS_RD2022_AZURE = Compliance( ) ENS_RD2022_GCP = Compliance( Framework="ENS", - Name="ENS RD 311/2022", + Name="ENS RD 311/2022 - Categoría Alta", Provider="GCP", Version="RD2022", Description="The accreditation scheme of the ENS (National Security Scheme) has been developed by the Ministry of Finance and Public Administrations and the CCN (National Cryptological Center). This includes the basic principles and minimum requirements necessary for the adequate protection of information.", diff --git a/tests/lib/scan/scan_test.py b/tests/lib/scan/scan_test.py index 1699902e12..e6ff948ed7 100644 --- a/tests/lib/scan/scan_test.py +++ b/tests/lib/scan/scan_test.py @@ -260,16 +260,24 @@ class TestScan: assert scan.get_completed_services() == set() assert scan.get_completed_checks() == set() - @patch("importlib.import_module") + @patch("prowler.lib.scan.scan.load_checks_to_execute") + @patch("prowler.lib.scan.scan.update_checks_metadata_with_compliance") + @patch("prowler.lib.scan.scan.Compliance.get_bulk") + @patch("prowler.lib.scan.scan.CheckMetadata.get_bulk") + @patch("prowler.lib.scan.scan.import_check") def test_scan( - mock_import_module, + self, + mock_import_check, + mock_get_bulk, + mock_compliance_get_bulk, + mock_update_checks_metadata, + mock_load_checks, mock_global_provider, mock_execute, mock_logger, - mock_generate_output, - mock_recover_checks_from_provider, - mock_load_check_metadata, ): + from prowler.lib.check.models import Severity + mock_check_class = MagicMock() mock_check_instance = mock_check_class.return_value mock_check_instance.Provider = "aws" @@ -277,23 +285,39 @@ class TestScan: mock_check_instance.CheckTitle = "Check if IAM Access Analyzer is enabled" mock_check_instance.Categories = [] - mock_import_module.return_value = MagicMock( + mock_import_check.return_value = MagicMock( accessanalyzer_enabled=mock_check_class ) checks_to_execute = {"accessanalyzer_enabled"} custom_checks_metadata = {} - mock_global_provider.type = "aws" + + # Mock CheckMetadata + mock_metadata = MagicMock() + mock_metadata.CheckID = "accessanalyzer_enabled" + mock_metadata.ResourceType = "AWS::IAM::AccessAnalyzer" + mock_metadata.Categories = [] + mock_metadata.CheckAliases = [] + mock_metadata.Severity = Severity.medium + mock_metadata.Compliance = [] + + bulk_checks_metadata = {"accessanalyzer_enabled": mock_metadata} + mock_get_bulk.return_value = bulk_checks_metadata + + # Mock update_checks_metadata_with_compliance to return the same metadata + mock_update_checks_metadata.return_value = bulk_checks_metadata + + # Mock Compliance frameworks + mock_compliance_get_bulk.return_value = {} + + # Mock load_checks_to_execute to return the checks + mock_load_checks.return_value = ["accessanalyzer_enabled"] scan = Scan(mock_global_provider, checks=checks_to_execute) - mock_load_check_metadata.assert_called_once() - mock_recover_checks_from_provider.assert_called_once_with("aws") results = list(scan.scan(custom_checks_metadata)) - assert mock_generate_output.call_count == 1 * len(mock_execute.side_effect()) assert mock_execute.call_count == 1 assert len(results) == 1 - assert results[0][1] == mock_execute.side_effect() assert results[0][0] == 100.0 assert scan.progress == 100.0 # Since the scan is mocked, the duration will always be 0 for now diff --git a/tests/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest_test.py b/tests/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest_test.py index 621ecc2457..8fb4f94980 100644 --- a/tests/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest_test.py +++ b/tests/providers/aws/services/firehose/firehose_stream_encrypted_at_rest/firehose_stream_encrypted_at_rest_test.py @@ -198,7 +198,7 @@ class Test_firehose_stream_encrypted_at_rest: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Firehose Stream {stream_name} does not have at rest encryption enabled or the source stream is not encrypted." + == f"Firehose Stream {stream_name} does not have at rest encryption enabled." ) @mock_aws @@ -253,7 +253,7 @@ class Test_firehose_stream_encrypted_at_rest: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Firehose Stream {stream_name} does not have at rest encryption enabled or the source stream is not encrypted." + == f"Firehose Stream {stream_name} does not have at rest encryption enabled." ) @mock_aws @@ -319,12 +319,149 @@ class Test_firehose_stream_encrypted_at_rest: result = check.execute() assert len(result) == 1 - assert result[0].status == "PASS" + assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Firehose Stream {stream_name} does not have at rest encryption enabled but the source stream test-kinesis-stream has at rest encryption enabled." + == f"Firehose Stream {stream_name} does not have at rest encryption enabled even though source stream test-kinesis-stream has at rest encryption enabled." ) + @mock_aws + def test_stream_kinesis_source_encrypted_firehose_encryption_enabled(self): + # Generate Kinesis client + kinesis_client = client("kinesis", region_name=AWS_REGION_EU_WEST_1) + kinesis_client.create_stream( + StreamName="test-kinesis-stream", + ShardCount=1, + ) + + kinesis_stream_arn = f"arn:aws:kinesis:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:stream/test-kinesis-stream" + + # Enable encryption on the Kinesis stream + kinesis_client.start_stream_encryption( + StreamName="test-kinesis-stream", + EncryptionType="KMS", + KeyId=f"arn:aws:kms:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:key/test-kms-key-id", + ) + + # Generate Firehose client + firehose = client("firehose", region_name=AWS_REGION_EU_WEST_1) + delivery_stream = firehose.create_delivery_stream( + DeliveryStreamName="test-delivery-stream", + DeliveryStreamType="KinesisStreamAsSource", + KinesisStreamSourceConfiguration={ + "KinesisStreamARN": kinesis_stream_arn, + "RoleARN": "arn:aws:iam::012345678901:role/firehose-role", + }, + S3DestinationConfiguration={ + "RoleARN": "arn:aws:iam::012345678901:role/firehose-role", + "BucketARN": "arn:aws:s3:::test-bucket", + "Prefix": "", + "BufferingHints": {"IntervalInSeconds": 300, "SizeInMBs": 5}, + "CompressionFormat": "UNCOMPRESSED", + }, + ) + stream_name = delivery_stream["DeliveryStreamARN"].split("/")[-1] + + firehose.start_delivery_stream_encryption( + DeliveryStreamName=stream_name, + DeliveryStreamEncryptionConfigurationInput={ + "KeyType": "AWS_OWNED_CMK", + }, + ) + + from prowler.providers.aws.services.firehose.firehose_service import Firehose + from prowler.providers.aws.services.kinesis.kinesis_service import Kinesis + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch( + "prowler.providers.aws.services.firehose.firehose_stream_encrypted_at_rest.firehose_stream_encrypted_at_rest.firehose_client", + new=Firehose(aws_provider), + ), + mock.patch( + "prowler.providers.aws.services.firehose.firehose_stream_encrypted_at_rest.firehose_stream_encrypted_at_rest.kinesis_client", + new=Kinesis(aws_provider), + ), + ): + from prowler.providers.aws.services.firehose.firehose_stream_encrypted_at_rest.firehose_stream_encrypted_at_rest import ( + firehose_stream_encrypted_at_rest, + ) + + check = firehose_stream_encrypted_at_rest() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Firehose Stream {stream_name} does have at rest encryption enabled." + ) + + @mock_aws + def test_stream_kinesis_source_not_encrypted(self): + # Generate Kinesis client + kinesis_client = client("kinesis", region_name=AWS_REGION_EU_WEST_1) + kinesis_client.create_stream( + StreamName="test-kinesis-stream", + ShardCount=1, + ) + kinesis_stream_arn = f"arn:aws:kinesis:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:stream/test-kinesis-stream" + + # Generate Firehose client + firehose_client = client("firehose", region_name=AWS_REGION_EU_WEST_1) + delivery_stream = firehose_client.create_delivery_stream( + DeliveryStreamName="test-delivery-stream", + DeliveryStreamType="KinesisStreamAsSource", + KinesisStreamSourceConfiguration={ + "KinesisStreamARN": kinesis_stream_arn, + "RoleARN": "arn:aws:iam::012345678901:role/firehose-role", + }, + S3DestinationConfiguration={ + "RoleARN": "arn:aws:iam::012345678901:role/firehose-role", + "BucketARN": "arn:aws:s3:::test-bucket", + "Prefix": "", + "BufferingHints": {"IntervalInSeconds": 300, "SizeInMBs": 5}, + "CompressionFormat": "UNCOMPRESSED", + }, + ) + stream_name = delivery_stream["DeliveryStreamARN"].split("/")[-1] + + from prowler.providers.aws.services.firehose.firehose_service import Firehose + from prowler.providers.aws.services.kinesis.kinesis_service import Kinesis + + aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1]) + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch( + "prowler.providers.aws.services.firehose.firehose_stream_encrypted_at_rest.firehose_stream_encrypted_at_rest.firehose_client", + new=Firehose(aws_provider), + ), + mock.patch( + "prowler.providers.aws.services.firehose.firehose_stream_encrypted_at_rest.firehose_stream_encrypted_at_rest.kinesis_client", + new=Kinesis(aws_provider), + ), + ): + from prowler.providers.aws.services.firehose.firehose_stream_encrypted_at_rest.firehose_stream_encrypted_at_rest import ( + firehose_stream_encrypted_at_rest, + ) + + check = firehose_stream_encrypted_at_rest() + result = check.execute() + + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Firehose Stream {stream_name} does not have at rest encryption enabled and the source stream test-kinesis-stream is not encrypted at rest." + ) + @mock_aws def test_stream_kinesis_source_not_found(self): """Test case when Kinesis source stream is not found - should handle None gracefully""" @@ -377,5 +514,5 @@ class Test_firehose_stream_encrypted_at_rest: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Firehose Stream {stream_name} does not have at rest encryption enabled or the source stream is not encrypted." + == f"Firehose Stream {stream_name} does not have at rest encryption enabled and the referenced source stream could not be found." ) diff --git a/tests/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited_test.py b/tests/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited_test.py new file mode 100644 index 0000000000..2bacd5dda1 --- /dev/null +++ b/tests/providers/github/services/organization/organization_repository_creation_limited/organization_repository_creation_limited_test.py @@ -0,0 +1,170 @@ +from unittest import mock + +from prowler.providers.github.services.organization.organization_service import Org +from tests.providers.github.github_fixtures import set_mocked_github_provider + + +class Test_organization_repository_creation_limited: + def test_no_organizations(self): + organization_client = mock.MagicMock + organization_client.organizations = {} + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_github_provider(), + ), + mock.patch( + "prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited.organization_client", + new=organization_client, + ), + ): + from prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited import ( + organization_repository_creation_limited, + ) + + check = organization_repository_creation_limited() + result = check.execute() + assert len(result) == 0 + + def test_repository_creation_disabled_globally(self): + organization_client = mock.MagicMock + org_name = "test-organization" + organization_client.organizations = { + 1: Org( + id=1, + name=org_name, + mfa_required=None, + members_can_create_repositories=False, + ), + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_github_provider(), + ), + mock.patch( + "prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited.organization_client", + new=organization_client, + ), + ): + from prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited import ( + organization_repository_creation_limited, + ) + + check = organization_repository_creation_limited() + result = check.execute() + assert len(result) == 1 + assert result[0].resource_name == org_name + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Organization {org_name} has disabled repository creation for members." + ) + + def test_repository_creation_allowed_for_members(self): + organization_client = mock.MagicMock + org_name = "test-organization" + organization_client.organizations = { + 1: Org( + id=1, + name=org_name, + mfa_required=None, + members_can_create_repositories=True, + members_can_create_public_repositories=True, + ), + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_github_provider(), + ), + mock.patch( + "prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited.organization_client", + new=organization_client, + ), + ): + from prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited import ( + organization_repository_creation_limited, + ) + + check = organization_repository_creation_limited() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert "public repositories" in result[0].status_extended + assert "repositories of any type" in result[0].status_extended + + def test_repository_creation_disabled_per_visibility(self): + organization_client = mock.MagicMock + org_name = "test-organization" + organization_client.organizations = { + 1: Org( + id=1, + name=org_name, + mfa_required=None, + members_can_create_public_repositories=False, + members_can_create_private_repositories=False, + members_can_create_internal_repositories=False, + ), + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_github_provider(), + ), + mock.patch( + "prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited.organization_client", + new=organization_client, + ), + ): + from prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited import ( + organization_repository_creation_limited, + ) + + check = organization_repository_creation_limited() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Organization {org_name} has disabled repository creation for members." + ) + + def test_repository_creation_disabled_via_members_allowed_type(self): + organization_client = mock.MagicMock + org_name = "test-organization" + organization_client.organizations = { + 1: Org( + id=1, + name=org_name, + mfa_required=None, + members_allowed_repository_creation_type="none", + ), + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_github_provider(), + ), + mock.patch( + "prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited.organization_client", + new=organization_client, + ), + ): + from prowler.providers.github.services.organization.organization_repository_creation_limited.organization_repository_creation_limited import ( + organization_repository_creation_limited, + ) + + check = organization_repository_creation_limited() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Organization {org_name} has disabled repository creation for members." + ) diff --git a/tests/providers/iac/iac_fixtures.py b/tests/providers/iac/iac_fixtures.py index 9e4c1105f4..2e769a732a 100644 --- a/tests/providers/iac/iac_fixtures.py +++ b/tests/providers/iac/iac_fixtures.py @@ -17,6 +17,10 @@ SAMPLE_TRIVY_OUTPUT = { "Severity": "LOW", "PrimaryURL": "https://avd.aquasec.com/misconfig/aws/s3/avd-aws-0001", "RuleID": "AVD-AWS-0001", + "CauseMetadata": { + "StartLine": 10, + "EndLine": 15, + }, }, { "ID": "AVD-AWS-0002", @@ -27,6 +31,10 @@ SAMPLE_TRIVY_OUTPUT = { "Severity": "LOW", "PrimaryURL": "https://avd.aquasec.com/misconfig/aws/s3/avd-aws-0002", "RuleID": "AVD-AWS-0002", + "CauseMetadata": { + "StartLine": 20, + "EndLine": 25, + }, }, ], "Vulnerabilities": [], @@ -46,6 +54,10 @@ SAMPLE_TRIVY_OUTPUT = { "Severity": "LOW", "PrimaryURL": "https://avd.aquasec.com/misconfig/aws/s3/avd-aws-0003", "RuleID": "AVD-AWS-0003", + "CauseMetadata": { + "StartLine": 30, + "EndLine": 35, + }, } ], "Vulnerabilities": [], @@ -67,6 +79,10 @@ SAMPLE_FAILED_CHECK = { "Severity": "low", "PrimaryURL": "https://avd.aquasec.com/misconfig/aws/s3/avd-aws-0001", "RuleID": "AVD-AWS-0001", + "CauseMetadata": { + "StartLine": 10, + "EndLine": 15, + }, } SAMPLE_PASSED_CHECK = { @@ -78,6 +94,10 @@ SAMPLE_PASSED_CHECK = { "Severity": "low", "PrimaryURL": "https://avd.aquasec.com/misconfig/aws/s3/avd-aws-0003", "RuleID": "AVD-AWS-0003", + "CauseMetadata": { + "StartLine": 30, + "EndLine": 35, + }, } # Additional sample checks diff --git a/tests/providers/iac/iac_provider_test.py b/tests/providers/iac/iac_provider_test.py index 7f89ff7a49..8fb6fc48f9 100644 --- a/tests/providers/iac/iac_provider_test.py +++ b/tests/providers/iac/iac_provider_test.py @@ -86,9 +86,12 @@ class TestIacProvider: stdout=get_sample_trivy_json_output(), stderr="" ) - reports = provider.run_scan( + # Collect all batches from the generator + reports = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + reports.extend(batch) # Should have 3 misconfigurations from the sample output assert len(reports) == 3 @@ -124,9 +127,11 @@ class TestIacProvider: stdout=get_empty_trivy_output(), stderr="" ) - reports = provider.run_scan( + reports = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + reports.extend(batch) assert len(reports) == 0 def test_provider_run_local_scan(self): @@ -200,7 +205,9 @@ class TestIacProvider: ) with pytest.raises(SystemExit) as excinfo: - provider.run_scan("/test/directory", ["all"], []) + # Consume the generator + for _ in provider.run_scan("/test/directory", ["all"], []): + pass assert excinfo.value.code == 1 @@ -212,7 +219,11 @@ class TestIacProvider: mock_subprocess.return_value = MagicMock(stdout="null", stderr="") with pytest.raises(SystemExit) as exc_info: - provider.run_scan("/test/directory", ["vuln", "misconfig", "secret"], []) + # Consume the generator + for _ in provider.run_scan( + "/test/directory", ["vuln", "misconfig", "secret"], [] + ): + pass assert exc_info.value.code == 1 def test_iac_provider_process_finding_dockerfile(self): @@ -264,9 +275,11 @@ class TestIacProvider: stdout=json.dumps(sample_output), stderr="" ) - result = provider.run_scan( + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + result.extend(batch) # Verify results assert len(result) == 2 @@ -299,9 +312,11 @@ class TestIacProvider: stdout=json.dumps(sample_output), stderr="" ) - result = provider.run_scan( + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], ["exclude/path"] - ) + ): + result.extend(batch) # Verify results assert len(result) == 1 @@ -318,9 +333,11 @@ class TestIacProvider: stdout=json.dumps({"Results": []}), stderr="" ) - result = provider.run_scan( + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + result.extend(batch) # Verify results assert len(result) == 0 @@ -356,9 +373,11 @@ class TestIacProvider: stdout=json.dumps(sample_output), stderr="" ) - result = provider.run_scan( + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + result.extend(batch) # Verify results assert len(result) == 2 @@ -377,7 +396,11 @@ class TestIacProvider: mock_subprocess.side_effect = Exception("Test exception") with pytest.raises(SystemExit) as exc_info: - provider.run_scan("/test/directory", ["vuln", "misconfig", "secret"], []) + # Consume the generator + for _ in provider.run_scan( + "/test/directory", ["vuln", "misconfig", "secret"], [] + ): + pass assert exc_info.value.code == 1 @@ -405,7 +428,9 @@ class TestIacProvider: # Test with specific scanners scanners = ["vuln", "misconfig", "secret"] - result = provider.run_scan("/test/directory", scanners, []) + result = [] + for batch in provider.run_scan("/test/directory", scanners, []): + result.extend(batch) # Verify subprocess was called with correct scanners mock_subprocess.assert_called_once_with( @@ -453,9 +478,11 @@ class TestIacProvider: # Test with exclude paths exclude_paths = ["node_modules", ".git", "vendor"] - result = provider.run_scan( + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], exclude_paths - ) + ): + result.extend(batch) # Verify subprocess was called with correct exclude paths expected_command = [ @@ -510,9 +537,12 @@ class TestIacProvider: stdout=json.dumps(sample_output), stderr="" ) - result = provider.run_scan( + # Consume the generator to get all batches + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + result.extend(batch) # Verify results assert len(result) == 5 # 5 misconfigurations @@ -536,9 +566,12 @@ class TestIacProvider: stdout=json.dumps({"Results": []}), stderr="" ) - result = provider.run_scan( + # Consume the generator to get all batches + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + result.extend(batch) # Verify results assert len(result) == 0 @@ -592,9 +625,12 @@ class TestIacProvider: stdout=json.dumps(sample_output), stderr="" ) - result = provider.run_scan( + # Consume the generator to get all batches + result = [] + for batch in provider.run_scan( "/test/directory", ["vuln", "misconfig", "secret"], [] - ) + ): + result.extend(batch) # Verify results assert ( @@ -615,7 +651,8 @@ class TestIacProvider: ) with patch.object(provider, "run_scan") as mock_run_scan: - mock_run_scan.return_value = [] + # Mock should return a generator (empty in this case) + mock_run_scan.return_value = iter([]) provider.run() mock_run_scan.assert_called_once_with( diff --git a/tests/providers/oraclecloud/conftest.py b/tests/providers/oraclecloud/conftest.py index aeeb41f043..1c29b64cdf 100644 --- a/tests/providers/oraclecloud/conftest.py +++ b/tests/providers/oraclecloud/conftest.py @@ -18,27 +18,27 @@ class MockOCIModule(MagicMock): return MagicMock() -# Only mock if oci import fails (missing dependencies) +# Only mock if oraclecloud import fails (missing dependencies) try: pass except (ImportError, ModuleNotFoundError): # Create mock OCI module mock_oci = MockOCIModule() - sys.modules["oci"] = mock_oci - sys.modules["oci.auth"] = mock_oci.auth - sys.modules["oci.config"] = mock_oci.config - sys.modules["oci.identity"] = mock_oci.identity - sys.modules["oci.core"] = mock_oci.core - sys.modules["oci.object_storage"] = mock_oci.object_storage - sys.modules["oci.key_management"] = mock_oci.key_management - sys.modules["oci.file_storage"] = mock_oci.file_storage - sys.modules["oci.block_storage"] = mock_oci.block_storage - sys.modules["oci.database"] = mock_oci.database - sys.modules["oci.events"] = mock_oci.events - sys.modules["oci.cloud_guard"] = mock_oci.cloud_guard - sys.modules["oci.audit"] = mock_oci.audit - sys.modules["oci.analytics"] = mock_oci.analytics - sys.modules["oci.integration"] = mock_oci.integration - sys.modules["oci.logging"] = mock_oci.logging - sys.modules["oci.pagination"] = mock_oci.pagination - sys.modules["oci.exceptions"] = mock_oci.exceptions + sys.modules["oraclecloud"] = mock_oci + sys.modules["oraclecloud.auth"] = mock_oci.auth + sys.modules["oraclecloud.config"] = mock_oci.config + sys.modules["oraclecloud.identity"] = mock_oci.identity + sys.modules["oraclecloud.core"] = mock_oci.core + sys.modules["oraclecloud.object_storage"] = mock_oci.object_storage + sys.modules["oraclecloud.key_management"] = mock_oci.key_management + sys.modules["oraclecloud.file_storage"] = mock_oci.file_storage + sys.modules["oraclecloud.block_storage"] = mock_oci.block_storage + sys.modules["oraclecloud.database"] = mock_oci.database + sys.modules["oraclecloud.events"] = mock_oci.events + sys.modules["oraclecloud.cloud_guard"] = mock_oci.cloud_guard + sys.modules["oraclecloud.audit"] = mock_oci.audit + sys.modules["oraclecloud.analytics"] = mock_oci.analytics + sys.modules["oraclecloud.integration"] = mock_oci.integration + sys.modules["oraclecloud.logging"] = mock_oci.logging + sys.modules["oraclecloud.pagination"] = mock_oci.pagination + sys.modules["oraclecloud.exceptions"] = mock_oci.exceptions diff --git a/tests/providers/oraclecloud/oci_fixtures.py b/tests/providers/oraclecloud/oci_fixtures.py index a83a44cb2d..b1ebef62d9 100644 --- a/tests/providers/oraclecloud/oci_fixtures.py +++ b/tests/providers/oraclecloud/oci_fixtures.py @@ -16,7 +16,7 @@ OCI_USER_ID = "ocid1.user.oc1..aaaaaaaexample" OCI_REGION = "us-ashburn-1" -def set_mocked_oci_provider( +def set_mocked_oraclecloud_provider( tenancy_id: str = OCI_TENANCY_ID, tenancy_name: str = OCI_TENANCY_NAME, user_id: str = OCI_USER_ID, @@ -24,7 +24,7 @@ def set_mocked_oci_provider( ) -> MagicMock: """Create a mocked OCI provider for testing""" provider = MagicMock() - provider.type = "oci" + provider.type = "oraclecloud" # Mock session provider.session = OCISession( diff --git a/tests/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted_test.py b/tests/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted_test.py index af44a791e2..79ad464540 100644 --- a/tests/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted_test.py +++ b/tests/providers/oraclecloud/services/analytics/analytics_instance_access_restricted/analytics_instance_access_restricted_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_analytics_instance_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.analytics.analytics_instance_access_restricted.analytics_instance_access_restricted.analytics_client", @@ -102,7 +102,7 @@ class Test_analytics_instance_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.analytics.analytics_instance_access_restricted.analytics_instance_access_restricted.analytics_client", @@ -136,7 +136,7 @@ class Test_analytics_instance_access_restricted: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "analytics_instance_access_restricted" @@ -187,7 +187,7 @@ class Test_analytics_instance_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.analytics.analytics_instance_access_restricted.analytics_instance_access_restricted.analytics_client", @@ -221,7 +221,7 @@ class Test_analytics_instance_access_restricted: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "analytics_instance_access_restricted" diff --git a/tests/providers/oraclecloud/services/analytics/analytics_service_test.py b/tests/providers/oraclecloud/services/analytics/analytics_service_test.py index bfafd798e1..02267a8c0e 100644 --- a/tests/providers/oraclecloud/services/analytics/analytics_service_test.py +++ b/tests/providers/oraclecloud/services/analytics/analytics_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestAnalyticsService: def test_service(self): """Test that analytics service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestAnalyticsService: Analytics, ) - analytics_client = Analytics(oci_provider) + analytics_client = Analytics(oraclecloud_provider) # Manually set required attributes since __init__ was mocked analytics_client.service = "analytics" - analytics_client.provider = oci_provider + analytics_client.provider = oraclecloud_provider analytics_client.audited_compartments = {} analytics_client.regional_clients = {} # Verify service name assert analytics_client.service == "analytics" - assert analytics_client.provider == oci_provider + assert analytics_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days_test.py b/tests/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days_test.py index d5e7488721..972e261a57 100644 --- a/tests/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days_test.py +++ b/tests/providers/oraclecloud/services/audit/audit_log_retention_period_365_days/audit_log_retention_period_365_days_test.py @@ -3,7 +3,7 @@ from unittest import mock from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -18,7 +18,7 @@ class Test_audit_log_retention_period_365_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.audit.audit_log_retention_period_365_days.audit_log_retention_period_365_days.audit_client", @@ -51,7 +51,7 @@ class Test_audit_log_retention_period_365_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.audit.audit_log_retention_period_365_days.audit_log_retention_period_365_days.audit_client", @@ -84,7 +84,7 @@ class Test_audit_log_retention_period_365_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.audit.audit_log_retention_period_365_days.audit_log_retention_period_365_days.audit_client", diff --git a/tests/providers/oraclecloud/services/audit/audit_service_test.py b/tests/providers/oraclecloud/services/audit/audit_service_test.py index 06adc4576b..ab3710fa3d 100644 --- a/tests/providers/oraclecloud/services/audit/audit_service_test.py +++ b/tests/providers/oraclecloud/services/audit/audit_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestAuditService: def test_service(self): """Test that audit service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -15,14 +15,14 @@ class TestAuditService: ): from prowler.providers.oraclecloud.services.audit.audit_service import Audit - audit_client = Audit(oci_provider) + audit_client = Audit(oraclecloud_provider) # Manually set required attributes since __init__ was mocked audit_client.service = "audit" - audit_client.provider = oci_provider + audit_client.provider = oraclecloud_provider audit_client.audited_compartments = {} audit_client.regional_clients = {} # Verify service name assert audit_client.service == "audit" - assert audit_client.provider == oci_provider + assert audit_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk_test.py b/tests/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk_test.py index c201f35168..7a8aea77ef 100644 --- a/tests/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk_test.py +++ b/tests/providers/oraclecloud/services/blockstorage/blockstorage_block_volume_encrypted_with_cmk/blockstorage_block_volume_encrypted_with_cmk_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -43,7 +43,7 @@ class Test_blockstorage_block_volume_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.blockstorage.blockstorage_block_volume_encrypted_with_cmk.blockstorage_block_volume_encrypted_with_cmk.blockstorage_client", @@ -106,7 +106,7 @@ class Test_blockstorage_block_volume_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.blockstorage.blockstorage_block_volume_encrypted_with_cmk.blockstorage_block_volume_encrypted_with_cmk.blockstorage_client", @@ -140,7 +140,7 @@ class Test_blockstorage_block_volume_encrypted_with_cmk: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "blockstorage_block_volume_encrypted_with_cmk" @@ -193,7 +193,7 @@ class Test_blockstorage_block_volume_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.blockstorage.blockstorage_block_volume_encrypted_with_cmk.blockstorage_block_volume_encrypted_with_cmk.blockstorage_client", @@ -227,7 +227,7 @@ class Test_blockstorage_block_volume_encrypted_with_cmk: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "blockstorage_block_volume_encrypted_with_cmk" diff --git a/tests/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk_test.py b/tests/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk_test.py index e2e9ef489e..272a6fe3af 100644 --- a/tests/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk_test.py +++ b/tests/providers/oraclecloud/services/blockstorage/blockstorage_boot_volume_encrypted_with_cmk/blockstorage_boot_volume_encrypted_with_cmk_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -43,7 +43,7 @@ class Test_blockstorage_boot_volume_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.blockstorage.blockstorage_boot_volume_encrypted_with_cmk.blockstorage_boot_volume_encrypted_with_cmk.blockstorage_client", @@ -106,7 +106,7 @@ class Test_blockstorage_boot_volume_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.blockstorage.blockstorage_boot_volume_encrypted_with_cmk.blockstorage_boot_volume_encrypted_with_cmk.blockstorage_client", @@ -140,7 +140,7 @@ class Test_blockstorage_boot_volume_encrypted_with_cmk: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "blockstorage_boot_volume_encrypted_with_cmk" @@ -193,7 +193,7 @@ class Test_blockstorage_boot_volume_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.blockstorage.blockstorage_boot_volume_encrypted_with_cmk.blockstorage_boot_volume_encrypted_with_cmk.blockstorage_client", @@ -227,7 +227,7 @@ class Test_blockstorage_boot_volume_encrypted_with_cmk: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "blockstorage_boot_volume_encrypted_with_cmk" diff --git a/tests/providers/oraclecloud/services/blockstorage/blockstorage_service_test.py b/tests/providers/oraclecloud/services/blockstorage/blockstorage_service_test.py index 0dcba40f19..e6abd6d0d9 100644 --- a/tests/providers/oraclecloud/services/blockstorage/blockstorage_service_test.py +++ b/tests/providers/oraclecloud/services/blockstorage/blockstorage_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestBlockStorageService: def test_service(self): """Test that blockstorage service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestBlockStorageService: BlockStorage, ) - blockstorage_client = BlockStorage(oci_provider) + blockstorage_client = BlockStorage(oraclecloud_provider) # Manually set required attributes since __init__ was mocked blockstorage_client.service = "blockstorage" - blockstorage_client.provider = oci_provider + blockstorage_client.provider = oraclecloud_provider blockstorage_client.audited_compartments = {} blockstorage_client.regional_clients = {} # Verify service name assert blockstorage_client.service == "blockstorage" - assert blockstorage_client.provider == oci_provider + assert blockstorage_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled_test.py b/tests/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled_test.py index 4aa3cd6635..c45304edcc 100644 --- a/tests/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled_test.py +++ b/tests/providers/oraclecloud/services/cloudguard/cloudguard_enabled/cloudguard_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_cloudguard_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.cloudguard.cloudguard_enabled.cloudguard_enabled.cloudguard_client", @@ -102,7 +102,7 @@ class Test_cloudguard_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.cloudguard.cloudguard_enabled.cloudguard_enabled.cloudguard_client", @@ -136,7 +136,7 @@ class Test_cloudguard_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "cloudguard_enabled" ) @@ -186,7 +186,7 @@ class Test_cloudguard_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.cloudguard.cloudguard_enabled.cloudguard_enabled.cloudguard_client", @@ -220,7 +220,7 @@ class Test_cloudguard_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "cloudguard_enabled" ) diff --git a/tests/providers/oraclecloud/services/cloudguard/cloudguard_service_test.py b/tests/providers/oraclecloud/services/cloudguard/cloudguard_service_test.py index 53317d475b..e379b9f83c 100644 --- a/tests/providers/oraclecloud/services/cloudguard/cloudguard_service_test.py +++ b/tests/providers/oraclecloud/services/cloudguard/cloudguard_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestCloudguardService: def test_service(self): """Test that cloudguard service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestCloudguardService: CloudGuard, ) - cloudguard_client = CloudGuard(oci_provider) + cloudguard_client = CloudGuard(oraclecloud_provider) # Manually set required attributes since __init__ was mocked cloudguard_client.service = "cloudguard" - cloudguard_client.provider = oci_provider + cloudguard_client.provider = oraclecloud_provider cloudguard_client.audited_compartments = {} cloudguard_client.regional_clients = {} # Verify service name assert cloudguard_client.service == "cloudguard" - assert cloudguard_client.provider == oci_provider + assert cloudguard_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled_test.py b/tests/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled_test.py index 807a364460..207672352a 100644 --- a/tests/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled_test.py +++ b/tests/providers/oraclecloud/services/compute/compute_instance_in_transit_encryption_enabled/compute_instance_in_transit_encryption_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_compute_instance_in_transit_encryption_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_in_transit_encryption_enabled.compute_instance_in_transit_encryption_enabled.compute_client", @@ -102,7 +102,7 @@ class Test_compute_instance_in_transit_encryption_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_in_transit_encryption_enabled.compute_instance_in_transit_encryption_enabled.compute_client", @@ -136,7 +136,7 @@ class Test_compute_instance_in_transit_encryption_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "compute_instance_in_transit_encryption_enabled" @@ -187,7 +187,7 @@ class Test_compute_instance_in_transit_encryption_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_in_transit_encryption_enabled.compute_instance_in_transit_encryption_enabled.compute_client", @@ -221,7 +221,7 @@ class Test_compute_instance_in_transit_encryption_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "compute_instance_in_transit_encryption_enabled" diff --git a/tests/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled_test.py b/tests/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled_test.py index d695e8324e..22ed19ce92 100644 --- a/tests/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled_test.py +++ b/tests/providers/oraclecloud/services/compute/compute_instance_legacy_metadata_endpoint_disabled/compute_instance_legacy_metadata_endpoint_disabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_compute_instance_legacy_metadata_endpoint_disabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_legacy_metadata_endpoint_disabled.compute_instance_legacy_metadata_endpoint_disabled.compute_client", @@ -102,7 +102,7 @@ class Test_compute_instance_legacy_metadata_endpoint_disabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_legacy_metadata_endpoint_disabled.compute_instance_legacy_metadata_endpoint_disabled.compute_client", @@ -136,7 +136,7 @@ class Test_compute_instance_legacy_metadata_endpoint_disabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "compute_instance_legacy_metadata_endpoint_disabled" @@ -187,7 +187,7 @@ class Test_compute_instance_legacy_metadata_endpoint_disabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_legacy_metadata_endpoint_disabled.compute_instance_legacy_metadata_endpoint_disabled.compute_client", @@ -221,7 +221,7 @@ class Test_compute_instance_legacy_metadata_endpoint_disabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "compute_instance_legacy_metadata_endpoint_disabled" diff --git a/tests/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled_test.py b/tests/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled_test.py index e5be514363..62a80086e5 100644 --- a/tests/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled_test.py +++ b/tests/providers/oraclecloud/services/compute/compute_instance_secure_boot_enabled/compute_instance_secure_boot_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_compute_instance_secure_boot_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_secure_boot_enabled.compute_instance_secure_boot_enabled.compute_client", @@ -102,7 +102,7 @@ class Test_compute_instance_secure_boot_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_secure_boot_enabled.compute_instance_secure_boot_enabled.compute_client", @@ -136,7 +136,7 @@ class Test_compute_instance_secure_boot_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "compute_instance_secure_boot_enabled" @@ -187,7 +187,7 @@ class Test_compute_instance_secure_boot_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.compute.compute_instance_secure_boot_enabled.compute_instance_secure_boot_enabled.compute_client", @@ -221,7 +221,7 @@ class Test_compute_instance_secure_boot_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "compute_instance_secure_boot_enabled" diff --git a/tests/providers/oraclecloud/services/compute/compute_service_test.py b/tests/providers/oraclecloud/services/compute/compute_service_test.py index cd5a11ff09..f8adf08200 100644 --- a/tests/providers/oraclecloud/services/compute/compute_service_test.py +++ b/tests/providers/oraclecloud/services/compute/compute_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestComputeService: def test_service(self): """Test that compute service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestComputeService: Compute, ) - compute_client = Compute(oci_provider) + compute_client = Compute(oraclecloud_provider) # Manually set required attributes since __init__ was mocked compute_client.service = "compute" - compute_client.provider = oci_provider + compute_client.provider = oraclecloud_provider compute_client.audited_compartments = {} compute_client.regional_clients = {} # Verify service name assert compute_client.service == "compute" - assert compute_client.provider == oci_provider + assert compute_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted_test.py b/tests/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted_test.py index 38f4e8310e..a559fe6c8d 100644 --- a/tests/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted_test.py +++ b/tests/providers/oraclecloud/services/database/database_autonomous_database_access_restricted/database_autonomous_database_access_restricted_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_database_autonomous_database_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.database.database_autonomous_database_access_restricted.database_autonomous_database_access_restricted.database_client", @@ -102,7 +102,7 @@ class Test_database_autonomous_database_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.database.database_autonomous_database_access_restricted.database_autonomous_database_access_restricted.database_client", @@ -136,7 +136,7 @@ class Test_database_autonomous_database_access_restricted: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "database_autonomous_database_access_restricted" @@ -187,7 +187,7 @@ class Test_database_autonomous_database_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.database.database_autonomous_database_access_restricted.database_autonomous_database_access_restricted.database_client", @@ -221,7 +221,7 @@ class Test_database_autonomous_database_access_restricted: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "database_autonomous_database_access_restricted" diff --git a/tests/providers/oraclecloud/services/database/database_service_test.py b/tests/providers/oraclecloud/services/database/database_service_test.py index 6715f3dbe8..49ce51a401 100644 --- a/tests/providers/oraclecloud/services/database/database_service_test.py +++ b/tests/providers/oraclecloud/services/database/database_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestDatabaseService: def test_service(self): """Test that database service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestDatabaseService: Database, ) - database_client = Database(oci_provider) + database_client = Database(oraclecloud_provider) # Manually set required attributes since __init__ was mocked database_client.service = "database" - database_client.provider = oci_provider + database_client.provider = oraclecloud_provider database_client.audited_compartments = {} database_client.regional_clients = {} # Verify service name assert database_client.service == "database" - assert database_client.provider == oci_provider + assert database_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists_test.py b/tests/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists_test.py index 3d8ef06208..eeb39efd36 100644 --- a/tests/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists_test.py +++ b/tests/providers/oraclecloud/services/events/events_notification_topic_and_subscription_exists/events_notification_topic_and_subscription_exists_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_notification_topic_and_subscription_exists: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_notification_topic_and_subscription_exists.events_notification_topic_and_subscription_exists.events_client", @@ -102,7 +102,7 @@ class Test_events_notification_topic_and_subscription_exists: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_notification_topic_and_subscription_exists.events_notification_topic_and_subscription_exists.events_client", @@ -136,7 +136,7 @@ class Test_events_notification_topic_and_subscription_exists: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_notification_topic_and_subscription_exists" @@ -187,7 +187,7 @@ class Test_events_notification_topic_and_subscription_exists: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_notification_topic_and_subscription_exists.events_notification_topic_and_subscription_exists.events_client", @@ -221,7 +221,7 @@ class Test_events_notification_topic_and_subscription_exists: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_notification_topic_and_subscription_exists" diff --git a/tests/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems_test.py b/tests/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems_test.py index 25305934db..7b0010265d 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_cloudguard_problems/events_rule_cloudguard_problems_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_cloudguard_problems: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_cloudguard_problems.events_rule_cloudguard_problems.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_cloudguard_problems: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_cloudguard_problems.events_rule_cloudguard_problems.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_cloudguard_problems: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_cloudguard_problems" @@ -187,7 +187,7 @@ class Test_events_rule_cloudguard_problems: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_cloudguard_problems.events_rule_cloudguard_problems.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_cloudguard_problems: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_cloudguard_problems" diff --git a/tests/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes_test.py index 8cc8f179fc..0d17e9b8b5 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_iam_group_changes/events_rule_iam_group_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_iam_group_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_iam_group_changes.events_rule_iam_group_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_iam_group_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_iam_group_changes.events_rule_iam_group_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_iam_group_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_iam_group_changes" @@ -187,7 +187,7 @@ class Test_events_rule_iam_group_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_iam_group_changes.events_rule_iam_group_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_iam_group_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_iam_group_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes_test.py index 699947c060..b37347f6d2 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_iam_policy_changes/events_rule_iam_policy_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_iam_policy_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_iam_policy_changes.events_rule_iam_policy_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_iam_policy_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_iam_policy_changes.events_rule_iam_policy_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_iam_policy_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_iam_policy_changes" @@ -187,7 +187,7 @@ class Test_events_rule_iam_policy_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_iam_policy_changes.events_rule_iam_policy_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_iam_policy_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_iam_policy_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes_test.py index 9bc5da88fd..d8641551dc 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_identity_provider_changes/events_rule_identity_provider_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_identity_provider_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_identity_provider_changes.events_rule_identity_provider_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_identity_provider_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_identity_provider_changes.events_rule_identity_provider_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_identity_provider_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_identity_provider_changes" @@ -187,7 +187,7 @@ class Test_events_rule_identity_provider_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_identity_provider_changes.events_rule_identity_provider_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_identity_provider_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_identity_provider_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes_test.py index deb4d8698d..a322bfae58 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_idp_group_mapping_changes/events_rule_idp_group_mapping_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_idp_group_mapping_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_idp_group_mapping_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_idp_group_mapping_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_idp_group_mapping_changes" @@ -187,7 +187,7 @@ class Test_events_rule_idp_group_mapping_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_idp_group_mapping_changes.events_rule_idp_group_mapping_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_idp_group_mapping_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_idp_group_mapping_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication_test.py b/tests/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication_test.py index cc7f3ef9f8..10c2941a15 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_local_user_authentication/events_rule_local_user_authentication_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_local_user_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_local_user_authentication.events_rule_local_user_authentication.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_local_user_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_local_user_authentication.events_rule_local_user_authentication.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_local_user_authentication: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_local_user_authentication" @@ -187,7 +187,7 @@ class Test_events_rule_local_user_authentication: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_local_user_authentication.events_rule_local_user_authentication.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_local_user_authentication: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_local_user_authentication" diff --git a/tests/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes_test.py index b2aa44dace..0a14a54a4d 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_network_gateway_changes/events_rule_network_gateway_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_network_gateway_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_network_gateway_changes.events_rule_network_gateway_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_network_gateway_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_network_gateway_changes.events_rule_network_gateway_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_network_gateway_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_network_gateway_changes" @@ -187,7 +187,7 @@ class Test_events_rule_network_gateway_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_network_gateway_changes.events_rule_network_gateway_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_network_gateway_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_network_gateway_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes_test.py index 80db1bb60e..d900e0a2a6 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_network_security_group_changes/events_rule_network_security_group_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_network_security_group_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_network_security_group_changes.events_rule_network_security_group_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_network_security_group_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_network_security_group_changes.events_rule_network_security_group_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_network_security_group_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_network_security_group_changes" @@ -187,7 +187,7 @@ class Test_events_rule_network_security_group_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_network_security_group_changes.events_rule_network_security_group_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_network_security_group_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_network_security_group_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes_test.py index 545d8102e3..2a0e4f1bbd 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_route_table_changes/events_rule_route_table_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_route_table_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_route_table_changes.events_rule_route_table_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_route_table_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_route_table_changes.events_rule_route_table_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_route_table_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_route_table_changes" @@ -187,7 +187,7 @@ class Test_events_rule_route_table_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_route_table_changes.events_rule_route_table_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_route_table_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_route_table_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes_test.py index 548bf7084a..64f9c61483 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_security_list_changes/events_rule_security_list_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_security_list_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_security_list_changes.events_rule_security_list_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_security_list_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_security_list_changes.events_rule_security_list_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_security_list_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_security_list_changes" @@ -187,7 +187,7 @@ class Test_events_rule_security_list_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_security_list_changes.events_rule_security_list_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_security_list_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_security_list_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes_test.py index 91fb869fd0..cfe0e4b20a 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_user_changes/events_rule_user_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_user_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_user_changes.events_rule_user_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_user_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_user_changes.events_rule_user_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_user_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_user_changes" @@ -187,7 +187,7 @@ class Test_events_rule_user_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_user_changes.events_rule_user_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_user_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_user_changes" diff --git a/tests/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes_test.py b/tests/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes_test.py index 55967d1aa7..9181a57682 100644 --- a/tests/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes_test.py +++ b/tests/providers/oraclecloud/services/events/events_rule_vcn_changes/events_rule_vcn_changes_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_events_rule_vcn_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_vcn_changes.events_rule_vcn_changes.events_client", @@ -102,7 +102,7 @@ class Test_events_rule_vcn_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_vcn_changes.events_rule_vcn_changes.events_client", @@ -136,7 +136,7 @@ class Test_events_rule_vcn_changes: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "events_rule_vcn_changes" @@ -187,7 +187,7 @@ class Test_events_rule_vcn_changes: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.events.events_rule_vcn_changes.events_rule_vcn_changes.events_client", @@ -221,7 +221,7 @@ class Test_events_rule_vcn_changes: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "events_rule_vcn_changes" diff --git a/tests/providers/oraclecloud/services/events/events_service_test.py b/tests/providers/oraclecloud/services/events/events_service_test.py index 37c202b773..70baf617f1 100644 --- a/tests/providers/oraclecloud/services/events/events_service_test.py +++ b/tests/providers/oraclecloud/services/events/events_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestEventsService: def test_service(self): """Test that events service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestEventsService: Events, ) - events_client = Events(oci_provider) + events_client = Events(oraclecloud_provider) # Manually set required attributes since __init__ was mocked events_client.service = "events" - events_client.provider = oci_provider + events_client.provider = oraclecloud_provider events_client.audited_compartments = {} events_client.regional_clients = {} # Verify service name assert events_client.service == "events" - assert events_client.provider == oci_provider + assert events_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk_test.py b/tests/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk_test.py index ffca470502..58775d0413 100644 --- a/tests/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk_test.py +++ b/tests/providers/oraclecloud/services/filestorage/filestorage_file_system_encrypted_with_cmk/filestorage_file_system_encrypted_with_cmk_test.py @@ -5,7 +5,7 @@ import pytest from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -20,7 +20,7 @@ class Test_filestorage_file_system_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.filestorage.filestorage_file_system_encrypted_with_cmk.filestorage_file_system_encrypted_with_cmk.filestorage_client", diff --git a/tests/providers/oraclecloud/services/filestorage/filestorage_service_test.py b/tests/providers/oraclecloud/services/filestorage/filestorage_service_test.py index 426b1d12f8..e9497f0d2d 100644 --- a/tests/providers/oraclecloud/services/filestorage/filestorage_service_test.py +++ b/tests/providers/oraclecloud/services/filestorage/filestorage_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestFilestorageService: def test_service(self): """Test that filestorage service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestFilestorageService: Filestorage, ) - filestorage_client = Filestorage(oci_provider) + filestorage_client = Filestorage(oraclecloud_provider) # Manually set required attributes since __init__ was mocked filestorage_client.service = "filestorage" - filestorage_client.provider = oci_provider + filestorage_client.provider = oraclecloud_provider filestorage_client.audited_compartments = {} filestorage_client.regional_clients = {} # Verify service name assert filestorage_client.service == "filestorage" - assert filestorage_client.provider == oci_provider + assert filestorage_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins_test.py b/tests/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins_test.py index 1350fc69e6..0801effa32 100644 --- a/tests/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_iam_admins_cannot_update_tenancy_admins/identity_iam_admins_cannot_update_tenancy_admins_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_iam_admins_cannot_update_tenancy_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_iam_admins_cannot_update_tenancy_admins.identity_iam_admins_cannot_update_tenancy_admins.identity_client", @@ -102,7 +102,7 @@ class Test_identity_iam_admins_cannot_update_tenancy_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_iam_admins_cannot_update_tenancy_admins.identity_iam_admins_cannot_update_tenancy_admins.identity_client", @@ -136,7 +136,7 @@ class Test_identity_iam_admins_cannot_update_tenancy_admins: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_iam_admins_cannot_update_tenancy_admins" @@ -187,7 +187,7 @@ class Test_identity_iam_admins_cannot_update_tenancy_admins: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_iam_admins_cannot_update_tenancy_admins.identity_iam_admins_cannot_update_tenancy_admins.identity_client", @@ -221,7 +221,7 @@ class Test_identity_iam_admins_cannot_update_tenancy_admins: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_iam_admins_cannot_update_tenancy_admins" diff --git a/tests/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used_test.py b/tests/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used_test.py index 622a9602ce..171bfbd3d8 100644 --- a/tests/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_instance_principal_used/identity_instance_principal_used_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_instance_principal_used: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_instance_principal_used.identity_instance_principal_used.identity_client", @@ -102,7 +102,7 @@ class Test_identity_instance_principal_used: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_instance_principal_used.identity_instance_principal_used.identity_client", @@ -136,7 +136,7 @@ class Test_identity_instance_principal_used: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_instance_principal_used" @@ -187,7 +187,7 @@ class Test_identity_instance_principal_used: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_instance_principal_used.identity_instance_principal_used.identity_client", @@ -221,7 +221,7 @@ class Test_identity_instance_principal_used: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_instance_principal_used" diff --git a/tests/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment_test.py b/tests/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment_test.py index a8b6a72e04..d23b7cd4d8 100644 --- a/tests/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_no_resources_in_root_compartment/identity_no_resources_in_root_compartment_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_no_resources_in_root_compartment: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_no_resources_in_root_compartment.identity_no_resources_in_root_compartment.identity_client", @@ -102,7 +102,7 @@ class Test_identity_no_resources_in_root_compartment: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_no_resources_in_root_compartment.identity_no_resources_in_root_compartment.identity_client", @@ -136,7 +136,7 @@ class Test_identity_no_resources_in_root_compartment: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_no_resources_in_root_compartment" @@ -187,7 +187,7 @@ class Test_identity_no_resources_in_root_compartment: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_no_resources_in_root_compartment.identity_no_resources_in_root_compartment.identity_client", @@ -221,7 +221,7 @@ class Test_identity_no_resources_in_root_compartment: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_no_resources_in_root_compartment" diff --git a/tests/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists_test.py b/tests/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists_test.py index 42d5ebe0e2..6da2c6b0d4 100644 --- a/tests/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_non_root_compartment_exists/identity_non_root_compartment_exists_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_non_root_compartment_exists: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_non_root_compartment_exists.identity_non_root_compartment_exists.identity_client", @@ -102,7 +102,7 @@ class Test_identity_non_root_compartment_exists: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_non_root_compartment_exists.identity_non_root_compartment_exists.identity_client", @@ -136,7 +136,7 @@ class Test_identity_non_root_compartment_exists: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_non_root_compartment_exists" @@ -187,7 +187,7 @@ class Test_identity_non_root_compartment_exists: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_non_root_compartment_exists.identity_non_root_compartment_exists.identity_client", @@ -221,7 +221,7 @@ class Test_identity_non_root_compartment_exists: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_non_root_compartment_exists" diff --git a/tests/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days_test.py b/tests/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days_test.py index cbfd3df2e8..189aa115a5 100644 --- a/tests/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_password_policy_expires_within_365_days/identity_password_policy_expires_within_365_days_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_password_policy_expires_within_365_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_expires_within_365_days.identity_password_policy_expires_within_365_days.identity_client", @@ -102,7 +102,7 @@ class Test_identity_password_policy_expires_within_365_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_expires_within_365_days.identity_password_policy_expires_within_365_days.identity_client", @@ -136,7 +136,7 @@ class Test_identity_password_policy_expires_within_365_days: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_password_policy_expires_within_365_days" @@ -187,7 +187,7 @@ class Test_identity_password_policy_expires_within_365_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_expires_within_365_days.identity_password_policy_expires_within_365_days.identity_client", @@ -221,7 +221,7 @@ class Test_identity_password_policy_expires_within_365_days: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_password_policy_expires_within_365_days" diff --git a/tests/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14_test.py b/tests/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14_test.py index 40af84d011..f624bb3f14 100644 --- a/tests/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_password_policy_minimum_length_14/identity_password_policy_minimum_length_14_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_password_policy_minimum_length_14: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_minimum_length_14.identity_password_policy_minimum_length_14.identity_client", @@ -102,7 +102,7 @@ class Test_identity_password_policy_minimum_length_14: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_minimum_length_14.identity_password_policy_minimum_length_14.identity_client", @@ -136,7 +136,7 @@ class Test_identity_password_policy_minimum_length_14: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_password_policy_minimum_length_14" @@ -187,7 +187,7 @@ class Test_identity_password_policy_minimum_length_14: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_minimum_length_14.identity_password_policy_minimum_length_14.identity_client", @@ -221,7 +221,7 @@ class Test_identity_password_policy_minimum_length_14: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_password_policy_minimum_length_14" diff --git a/tests/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse_test.py b/tests/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse_test.py index 68713b7832..07a168ab4c 100644 --- a/tests/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_password_policy_prevents_reuse/identity_password_policy_prevents_reuse_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_password_policy_prevents_reuse: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_prevents_reuse.identity_password_policy_prevents_reuse.identity_client", @@ -102,7 +102,7 @@ class Test_identity_password_policy_prevents_reuse: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_prevents_reuse.identity_password_policy_prevents_reuse.identity_client", @@ -136,7 +136,7 @@ class Test_identity_password_policy_prevents_reuse: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_password_policy_prevents_reuse" @@ -187,7 +187,7 @@ class Test_identity_password_policy_prevents_reuse: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_password_policy_prevents_reuse.identity_password_policy_prevents_reuse.identity_client", @@ -221,7 +221,7 @@ class Test_identity_password_policy_prevents_reuse: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_password_policy_prevents_reuse" diff --git a/tests/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist_test.py b/tests/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist_test.py index d85008c6c1..6c03723fa0 100644 --- a/tests/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_service_level_admins_exist/identity_service_level_admins_exist_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_service_level_admins_exist: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_service_level_admins_exist.identity_service_level_admins_exist.identity_client", @@ -102,7 +102,7 @@ class Test_identity_service_level_admins_exist: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_service_level_admins_exist.identity_service_level_admins_exist.identity_client", @@ -136,7 +136,7 @@ class Test_identity_service_level_admins_exist: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_service_level_admins_exist" @@ -187,7 +187,7 @@ class Test_identity_service_level_admins_exist: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_service_level_admins_exist.identity_service_level_admins_exist.identity_client", @@ -221,7 +221,7 @@ class Test_identity_service_level_admins_exist: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_service_level_admins_exist" diff --git a/tests/providers/oraclecloud/services/identity/identity_service_test.py b/tests/providers/oraclecloud/services/identity/identity_service_test.py index 37284a273c..bb695d7128 100644 --- a/tests/providers/oraclecloud/services/identity/identity_service_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestIdentityService: def test_service(self): """Test that identity service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestIdentityService: Identity, ) - identity_client = Identity(oci_provider) + identity_client = Identity(oraclecloud_provider) # Manually set required attributes since __init__ was mocked identity_client.service = "identity" - identity_client.provider = oci_provider + identity_client.provider = oraclecloud_provider identity_client.audited_compartments = {} identity_client.regional_clients = {} # Verify service name assert identity_client.service == "identity" - assert identity_client.provider == oci_provider + assert identity_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited_test.py b/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited_test.py index 1514052306..ba9ecfba33 100644 --- a/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_permissions_limited/identity_tenancy_admin_permissions_limited_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_tenancy_admin_permissions_limited: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_tenancy_admin_permissions_limited.identity_tenancy_admin_permissions_limited.identity_client", @@ -102,7 +102,7 @@ class Test_identity_tenancy_admin_permissions_limited: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_tenancy_admin_permissions_limited.identity_tenancy_admin_permissions_limited.identity_client", @@ -136,7 +136,7 @@ class Test_identity_tenancy_admin_permissions_limited: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_tenancy_admin_permissions_limited" @@ -187,7 +187,7 @@ class Test_identity_tenancy_admin_permissions_limited: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_tenancy_admin_permissions_limited.identity_tenancy_admin_permissions_limited.identity_client", @@ -221,7 +221,7 @@ class Test_identity_tenancy_admin_permissions_limited: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_tenancy_admin_permissions_limited" diff --git a/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys_test.py b/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys_test.py index 51a2ab3609..664d3f1ed6 100644 --- a/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_tenancy_admin_users_no_api_keys/identity_tenancy_admin_users_no_api_keys_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_tenancy_admin_users_no_api_keys: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_tenancy_admin_users_no_api_keys.identity_tenancy_admin_users_no_api_keys.identity_client", @@ -102,7 +102,7 @@ class Test_identity_tenancy_admin_users_no_api_keys: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_tenancy_admin_users_no_api_keys.identity_tenancy_admin_users_no_api_keys.identity_client", @@ -136,7 +136,7 @@ class Test_identity_tenancy_admin_users_no_api_keys: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_tenancy_admin_users_no_api_keys" @@ -187,7 +187,7 @@ class Test_identity_tenancy_admin_users_no_api_keys: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_tenancy_admin_users_no_api_keys.identity_tenancy_admin_users_no_api_keys.identity_client", @@ -221,7 +221,7 @@ class Test_identity_tenancy_admin_users_no_api_keys: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_tenancy_admin_users_no_api_keys" diff --git a/tests/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days_test.py b/tests/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days_test.py index 0167d60e7d..0c42ea1c4e 100644 --- a/tests/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_user_api_keys_rotated_90_days/identity_user_api_keys_rotated_90_days_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_user_api_keys_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_api_keys_rotated_90_days.identity_user_api_keys_rotated_90_days.identity_client", @@ -102,7 +102,7 @@ class Test_identity_user_api_keys_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_api_keys_rotated_90_days.identity_user_api_keys_rotated_90_days.identity_client", @@ -136,7 +136,7 @@ class Test_identity_user_api_keys_rotated_90_days: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_user_api_keys_rotated_90_days" @@ -187,7 +187,7 @@ class Test_identity_user_api_keys_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_api_keys_rotated_90_days.identity_user_api_keys_rotated_90_days.identity_client", @@ -221,7 +221,7 @@ class Test_identity_user_api_keys_rotated_90_days: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_user_api_keys_rotated_90_days" diff --git a/tests/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days_test.py b/tests/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days_test.py index 4079a795c8..d0b7f8781f 100644 --- a/tests/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_user_auth_tokens_rotated_90_days/identity_user_auth_tokens_rotated_90_days_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_user_auth_tokens_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_auth_tokens_rotated_90_days.identity_user_auth_tokens_rotated_90_days.identity_client", @@ -102,7 +102,7 @@ class Test_identity_user_auth_tokens_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_auth_tokens_rotated_90_days.identity_user_auth_tokens_rotated_90_days.identity_client", @@ -136,7 +136,7 @@ class Test_identity_user_auth_tokens_rotated_90_days: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_user_auth_tokens_rotated_90_days" @@ -187,7 +187,7 @@ class Test_identity_user_auth_tokens_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_auth_tokens_rotated_90_days.identity_user_auth_tokens_rotated_90_days.identity_client", @@ -221,7 +221,7 @@ class Test_identity_user_auth_tokens_rotated_90_days: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_user_auth_tokens_rotated_90_days" diff --git a/tests/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days_test.py b/tests/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days_test.py index b17428f1f6..c5e98ac6b3 100644 --- a/tests/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_user_customer_secret_keys_rotated_90_days/identity_user_customer_secret_keys_rotated_90_days_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_user_customer_secret_keys_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_customer_secret_keys_rotated_90_days.identity_user_customer_secret_keys_rotated_90_days.identity_client", @@ -102,7 +102,7 @@ class Test_identity_user_customer_secret_keys_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_customer_secret_keys_rotated_90_days.identity_user_customer_secret_keys_rotated_90_days.identity_client", @@ -136,7 +136,7 @@ class Test_identity_user_customer_secret_keys_rotated_90_days: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_user_customer_secret_keys_rotated_90_days" @@ -187,7 +187,7 @@ class Test_identity_user_customer_secret_keys_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_customer_secret_keys_rotated_90_days.identity_user_customer_secret_keys_rotated_90_days.identity_client", @@ -221,7 +221,7 @@ class Test_identity_user_customer_secret_keys_rotated_90_days: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_user_customer_secret_keys_rotated_90_days" diff --git a/tests/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days_test.py b/tests/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days_test.py index 7e362e9d85..8d031640db 100644 --- a/tests/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_user_db_passwords_rotated_90_days/identity_user_db_passwords_rotated_90_days_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_user_db_passwords_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_db_passwords_rotated_90_days.identity_user_db_passwords_rotated_90_days.identity_client", @@ -102,7 +102,7 @@ class Test_identity_user_db_passwords_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_db_passwords_rotated_90_days.identity_user_db_passwords_rotated_90_days.identity_client", @@ -136,7 +136,7 @@ class Test_identity_user_db_passwords_rotated_90_days: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_user_db_passwords_rotated_90_days" @@ -187,7 +187,7 @@ class Test_identity_user_db_passwords_rotated_90_days: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_db_passwords_rotated_90_days.identity_user_db_passwords_rotated_90_days.identity_client", @@ -221,7 +221,7 @@ class Test_identity_user_db_passwords_rotated_90_days: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_user_db_passwords_rotated_90_days" diff --git a/tests/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access_test.py b/tests/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access_test.py index b55dd61581..534d40b22a 100644 --- a/tests/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_user_mfa_enabled_console_access/identity_user_mfa_enabled_console_access_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_user_mfa_enabled_console_access: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_mfa_enabled_console_access.identity_user_mfa_enabled_console_access.identity_client", @@ -102,7 +102,7 @@ class Test_identity_user_mfa_enabled_console_access: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_mfa_enabled_console_access.identity_user_mfa_enabled_console_access.identity_client", @@ -136,7 +136,7 @@ class Test_identity_user_mfa_enabled_console_access: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_user_mfa_enabled_console_access" @@ -187,7 +187,7 @@ class Test_identity_user_mfa_enabled_console_access: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_mfa_enabled_console_access.identity_user_mfa_enabled_console_access.identity_client", @@ -221,7 +221,7 @@ class Test_identity_user_mfa_enabled_console_access: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_user_mfa_enabled_console_access" diff --git a/tests/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address_test.py b/tests/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address_test.py index b476be1e87..c1e661b7db 100644 --- a/tests/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address_test.py +++ b/tests/providers/oraclecloud/services/identity/identity_user_valid_email_address/identity_user_valid_email_address_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_identity_user_valid_email_address: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_valid_email_address.identity_user_valid_email_address.identity_client", @@ -102,7 +102,7 @@ class Test_identity_user_valid_email_address: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_valid_email_address.identity_user_valid_email_address.identity_client", @@ -136,7 +136,7 @@ class Test_identity_user_valid_email_address: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "identity_user_valid_email_address" @@ -187,7 +187,7 @@ class Test_identity_user_valid_email_address: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.identity.identity_user_valid_email_address.identity_user_valid_email_address.identity_client", @@ -221,7 +221,7 @@ class Test_identity_user_valid_email_address: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "identity_user_valid_email_address" diff --git a/tests/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted_test.py b/tests/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted_test.py index 99ea00d511..42def0ee5b 100644 --- a/tests/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted_test.py +++ b/tests/providers/oraclecloud/services/integration/integration_instance_access_restricted/integration_instance_access_restricted_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_integration_instance_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.integration.integration_instance_access_restricted.integration_instance_access_restricted.integration_client", @@ -102,7 +102,7 @@ class Test_integration_instance_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.integration.integration_instance_access_restricted.integration_instance_access_restricted.integration_client", @@ -136,7 +136,7 @@ class Test_integration_instance_access_restricted: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "integration_instance_access_restricted" @@ -187,7 +187,7 @@ class Test_integration_instance_access_restricted: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.integration.integration_instance_access_restricted.integration_instance_access_restricted.integration_client", @@ -221,7 +221,7 @@ class Test_integration_instance_access_restricted: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "integration_instance_access_restricted" diff --git a/tests/providers/oraclecloud/services/integration/integration_service_test.py b/tests/providers/oraclecloud/services/integration/integration_service_test.py index 27170bb0c2..a1f8cf3825 100644 --- a/tests/providers/oraclecloud/services/integration/integration_service_test.py +++ b/tests/providers/oraclecloud/services/integration/integration_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestIntegrationService: def test_service(self): """Test that integration service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestIntegrationService: Integration, ) - integration_client = Integration(oci_provider) + integration_client = Integration(oraclecloud_provider) # Manually set required attributes since __init__ was mocked integration_client.service = "integration" - integration_client.provider = oci_provider + integration_client.provider = oraclecloud_provider integration_client.audited_compartments = {} integration_client.regional_clients = {} # Verify service name assert integration_client.service == "integration" - assert integration_client.provider == oci_provider + assert integration_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled_test.py b/tests/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled_test.py index 51ee56d597..bc9ec964a8 100644 --- a/tests/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled_test.py +++ b/tests/providers/oraclecloud/services/kms/kms_key_rotation_enabled/kms_key_rotation_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_kms_key_rotation_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.kms.kms_key_rotation_enabled.kms_key_rotation_enabled.kms_client", @@ -102,7 +102,7 @@ class Test_kms_key_rotation_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.kms.kms_key_rotation_enabled.kms_key_rotation_enabled.kms_client", @@ -136,7 +136,7 @@ class Test_kms_key_rotation_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "kms_key_rotation_enabled" @@ -187,7 +187,7 @@ class Test_kms_key_rotation_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.kms.kms_key_rotation_enabled.kms_key_rotation_enabled.kms_client", @@ -221,7 +221,7 @@ class Test_kms_key_rotation_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "kms_key_rotation_enabled" diff --git a/tests/providers/oraclecloud/services/kms/kms_service_test.py b/tests/providers/oraclecloud/services/kms/kms_service_test.py index 7b63287b62..3b87771ab8 100644 --- a/tests/providers/oraclecloud/services/kms/kms_service_test.py +++ b/tests/providers/oraclecloud/services/kms/kms_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestKmsService: def test_service(self): """Test that kms service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -15,14 +15,14 @@ class TestKmsService: ): from prowler.providers.oraclecloud.services.kms.kms_service import Kms - kms_client = Kms(oci_provider) + kms_client = Kms(oraclecloud_provider) # Manually set required attributes since __init__ was mocked kms_client.service = "kms" - kms_client.provider = oci_provider + kms_client.provider = oraclecloud_provider kms_client.audited_compartments = {} kms_client.regional_clients = {} # Verify service name assert kms_client.service == "kms" - assert kms_client.provider == oci_provider + assert kms_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/logging/logging_service_test.py b/tests/providers/oraclecloud/services/logging/logging_service_test.py index 3cea56d26b..dc52845a9f 100644 --- a/tests/providers/oraclecloud/services/logging/logging_service_test.py +++ b/tests/providers/oraclecloud/services/logging/logging_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestLoggingService: def test_service(self): """Test that logging service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestLoggingService: Logging, ) - logging_client = Logging(oci_provider) + logging_client = Logging(oraclecloud_provider) # Manually set required attributes since __init__ was mocked logging_client.service = "logging" - logging_client.provider = oci_provider + logging_client.provider = oraclecloud_provider logging_client.audited_compartments = {} logging_client.regional_clients = {} # Verify service name assert logging_client.service == "logging" - assert logging_client.provider == oci_provider + assert logging_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic_test.py b/tests/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic_test.py index 0678d7e5a2..c79c934146 100644 --- a/tests/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic_test.py +++ b/tests/providers/oraclecloud/services/network/network_default_security_list_restricts_traffic/network_default_security_list_restricts_traffic_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_network_default_security_list_restricts_traffic: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_default_security_list_restricts_traffic.network_default_security_list_restricts_traffic.network_client", @@ -102,7 +102,7 @@ class Test_network_default_security_list_restricts_traffic: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_default_security_list_restricts_traffic.network_default_security_list_restricts_traffic.network_client", @@ -136,7 +136,7 @@ class Test_network_default_security_list_restricts_traffic: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "network_default_security_list_restricts_traffic" @@ -187,7 +187,7 @@ class Test_network_default_security_list_restricts_traffic: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_default_security_list_restricts_traffic.network_default_security_list_restricts_traffic.network_client", @@ -221,7 +221,7 @@ class Test_network_default_security_list_restricts_traffic: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "network_default_security_list_restricts_traffic" diff --git a/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port_test.py b/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port_test.py index ec27474df6..55f94563c3 100644 --- a/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port_test.py +++ b/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_rdp_port/network_security_group_ingress_from_internet_to_rdp_port_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_network_security_group_ingress_from_internet_to_rdp_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_group_ingress_from_internet_to_rdp_port.network_security_group_ingress_from_internet_to_rdp_port.network_client", @@ -102,7 +102,7 @@ class Test_network_security_group_ingress_from_internet_to_rdp_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_group_ingress_from_internet_to_rdp_port.network_security_group_ingress_from_internet_to_rdp_port.network_client", @@ -136,7 +136,7 @@ class Test_network_security_group_ingress_from_internet_to_rdp_port: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "network_security_group_ingress_from_internet_to_rdp_port" @@ -187,7 +187,7 @@ class Test_network_security_group_ingress_from_internet_to_rdp_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_group_ingress_from_internet_to_rdp_port.network_security_group_ingress_from_internet_to_rdp_port.network_client", @@ -221,7 +221,7 @@ class Test_network_security_group_ingress_from_internet_to_rdp_port: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "network_security_group_ingress_from_internet_to_rdp_port" diff --git a/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port_test.py b/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port_test.py index 691256149b..baa7c49f12 100644 --- a/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port_test.py +++ b/tests/providers/oraclecloud/services/network/network_security_group_ingress_from_internet_to_ssh_port/network_security_group_ingress_from_internet_to_ssh_port_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_network_security_group_ingress_from_internet_to_ssh_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_group_ingress_from_internet_to_ssh_port.network_security_group_ingress_from_internet_to_ssh_port.network_client", @@ -102,7 +102,7 @@ class Test_network_security_group_ingress_from_internet_to_ssh_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_group_ingress_from_internet_to_ssh_port.network_security_group_ingress_from_internet_to_ssh_port.network_client", @@ -136,7 +136,7 @@ class Test_network_security_group_ingress_from_internet_to_ssh_port: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "network_security_group_ingress_from_internet_to_ssh_port" @@ -187,7 +187,7 @@ class Test_network_security_group_ingress_from_internet_to_ssh_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_group_ingress_from_internet_to_ssh_port.network_security_group_ingress_from_internet_to_ssh_port.network_client", @@ -221,7 +221,7 @@ class Test_network_security_group_ingress_from_internet_to_ssh_port: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "network_security_group_ingress_from_internet_to_ssh_port" diff --git a/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port_test.py b/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port_test.py index 7d8651deda..5d4cdb8875 100644 --- a/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port_test.py +++ b/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_rdp_port/network_security_list_ingress_from_internet_to_rdp_port_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_network_security_list_ingress_from_internet_to_rdp_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_list_ingress_from_internet_to_rdp_port.network_security_list_ingress_from_internet_to_rdp_port.network_client", @@ -102,7 +102,7 @@ class Test_network_security_list_ingress_from_internet_to_rdp_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_list_ingress_from_internet_to_rdp_port.network_security_list_ingress_from_internet_to_rdp_port.network_client", @@ -136,7 +136,7 @@ class Test_network_security_list_ingress_from_internet_to_rdp_port: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "network_security_list_ingress_from_internet_to_rdp_port" @@ -187,7 +187,7 @@ class Test_network_security_list_ingress_from_internet_to_rdp_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_list_ingress_from_internet_to_rdp_port.network_security_list_ingress_from_internet_to_rdp_port.network_client", @@ -221,7 +221,7 @@ class Test_network_security_list_ingress_from_internet_to_rdp_port: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "network_security_list_ingress_from_internet_to_rdp_port" diff --git a/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port_test.py b/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port_test.py index d8fef5465d..cb7c2875b7 100644 --- a/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port_test.py +++ b/tests/providers/oraclecloud/services/network/network_security_list_ingress_from_internet_to_ssh_port/network_security_list_ingress_from_internet_to_ssh_port_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_network_security_list_ingress_from_internet_to_ssh_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_list_ingress_from_internet_to_ssh_port.network_security_list_ingress_from_internet_to_ssh_port.network_client", @@ -102,7 +102,7 @@ class Test_network_security_list_ingress_from_internet_to_ssh_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_list_ingress_from_internet_to_ssh_port.network_security_list_ingress_from_internet_to_ssh_port.network_client", @@ -136,7 +136,7 @@ class Test_network_security_list_ingress_from_internet_to_ssh_port: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "network_security_list_ingress_from_internet_to_ssh_port" @@ -187,7 +187,7 @@ class Test_network_security_list_ingress_from_internet_to_ssh_port: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_security_list_ingress_from_internet_to_ssh_port.network_security_list_ingress_from_internet_to_ssh_port.network_client", @@ -221,7 +221,7 @@ class Test_network_security_list_ingress_from_internet_to_ssh_port: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "network_security_list_ingress_from_internet_to_ssh_port" diff --git a/tests/providers/oraclecloud/services/network/network_service_test.py b/tests/providers/oraclecloud/services/network/network_service_test.py index c73df8319c..6960e1d931 100644 --- a/tests/providers/oraclecloud/services/network/network_service_test.py +++ b/tests/providers/oraclecloud/services/network/network_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestNetworkService: def test_service(self): """Test that network service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestNetworkService: Network, ) - network_client = Network(oci_provider) + network_client = Network(oraclecloud_provider) # Manually set required attributes since __init__ was mocked network_client.service = "network" - network_client.provider = oci_provider + network_client.provider = oraclecloud_provider network_client.audited_compartments = {} network_client.regional_clients = {} # Verify service name assert network_client.service == "network" - assert network_client.provider == oci_provider + assert network_client.provider == oraclecloud_provider diff --git a/tests/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled_test.py b/tests/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled_test.py index 286dae00f4..ce41c90733 100644 --- a/tests/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled_test.py +++ b/tests/providers/oraclecloud/services/network/network_vcn_subnet_flow_logs_enabled/network_vcn_subnet_flow_logs_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -41,7 +41,7 @@ class Test_network_vcn_subnet_flow_logs_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_vcn_subnet_flow_logs_enabled.network_vcn_subnet_flow_logs_enabled.network_client", @@ -102,7 +102,7 @@ class Test_network_vcn_subnet_flow_logs_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_vcn_subnet_flow_logs_enabled.network_vcn_subnet_flow_logs_enabled.network_client", @@ -136,7 +136,7 @@ class Test_network_vcn_subnet_flow_logs_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "network_vcn_subnet_flow_logs_enabled" @@ -187,7 +187,7 @@ class Test_network_vcn_subnet_flow_logs_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.network.network_vcn_subnet_flow_logs_enabled.network_vcn_subnet_flow_logs_enabled.network_client", @@ -221,7 +221,7 @@ class Test_network_vcn_subnet_flow_logs_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "network_vcn_subnet_flow_logs_enabled" diff --git a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk_test.py b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk_test.py index ab0231996b..2632c61f8f 100644 --- a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk_test.py +++ b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_encrypted_with_cmk/objectstorage_bucket_encrypted_with_cmk_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -43,7 +43,7 @@ class Test_objectstorage_bucket_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_encrypted_with_cmk.objectstorage_bucket_encrypted_with_cmk.objectstorage_client", @@ -106,7 +106,7 @@ class Test_objectstorage_bucket_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_encrypted_with_cmk.objectstorage_bucket_encrypted_with_cmk.objectstorage_client", @@ -140,7 +140,7 @@ class Test_objectstorage_bucket_encrypted_with_cmk: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "objectstorage_bucket_encrypted_with_cmk" @@ -193,7 +193,7 @@ class Test_objectstorage_bucket_encrypted_with_cmk: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_encrypted_with_cmk.objectstorage_bucket_encrypted_with_cmk.objectstorage_client", @@ -227,7 +227,7 @@ class Test_objectstorage_bucket_encrypted_with_cmk: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "objectstorage_bucket_encrypted_with_cmk" diff --git a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled_test.py b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled_test.py index 708ae586a7..66239195ad 100644 --- a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled_test.py +++ b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_logging_enabled/objectstorage_bucket_logging_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -43,7 +43,7 @@ class Test_objectstorage_bucket_logging_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_logging_enabled.objectstorage_bucket_logging_enabled.objectstorage_client", @@ -106,7 +106,7 @@ class Test_objectstorage_bucket_logging_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_logging_enabled.objectstorage_bucket_logging_enabled.objectstorage_client", @@ -140,7 +140,7 @@ class Test_objectstorage_bucket_logging_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "objectstorage_bucket_logging_enabled" @@ -193,7 +193,7 @@ class Test_objectstorage_bucket_logging_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_logging_enabled.objectstorage_bucket_logging_enabled.objectstorage_client", @@ -227,7 +227,7 @@ class Test_objectstorage_bucket_logging_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "objectstorage_bucket_logging_enabled" diff --git a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible_test.py b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible_test.py index 6c1e8b200e..14e940dd6a 100644 --- a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible_test.py +++ b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_not_publicly_accessible/objectstorage_bucket_not_publicly_accessible_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -43,7 +43,7 @@ class Test_objectstorage_bucket_not_publicly_accessible: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_not_publicly_accessible.objectstorage_bucket_not_publicly_accessible.objectstorage_client", @@ -106,7 +106,7 @@ class Test_objectstorage_bucket_not_publicly_accessible: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_not_publicly_accessible.objectstorage_bucket_not_publicly_accessible.objectstorage_client", @@ -140,7 +140,7 @@ class Test_objectstorage_bucket_not_publicly_accessible: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "objectstorage_bucket_not_publicly_accessible" @@ -193,7 +193,7 @@ class Test_objectstorage_bucket_not_publicly_accessible: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_not_publicly_accessible.objectstorage_bucket_not_publicly_accessible.objectstorage_client", @@ -227,7 +227,7 @@ class Test_objectstorage_bucket_not_publicly_accessible: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "objectstorage_bucket_not_publicly_accessible" diff --git a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled_test.py b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled_test.py index 432db038ac..ce5d13c0ab 100644 --- a/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled_test.py +++ b/tests/providers/oraclecloud/services/objectstorage/objectstorage_bucket_versioning_enabled/objectstorage_bucket_versioning_enabled_test.py @@ -4,7 +4,7 @@ from tests.providers.oraclecloud.oci_fixtures import ( OCI_COMPARTMENT_ID, OCI_REGION, OCI_TENANCY_ID, - set_mocked_oci_provider, + set_mocked_oraclecloud_provider, ) @@ -43,7 +43,7 @@ class Test_objectstorage_bucket_versioning_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_versioning_enabled.objectstorage_bucket_versioning_enabled.objectstorage_client", @@ -106,7 +106,7 @@ class Test_objectstorage_bucket_versioning_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_versioning_enabled.objectstorage_bucket_versioning_enabled.objectstorage_client", @@ -140,7 +140,7 @@ class Test_objectstorage_bucket_versioning_enabled: assert pass_results[0].compartment_id is not None # Verify metadata - assert pass_results[0].check_metadata.Provider == "oci" + assert pass_results[0].check_metadata.Provider == "oraclecloud" assert ( pass_results[0].check_metadata.CheckID == "objectstorage_bucket_versioning_enabled" @@ -193,7 +193,7 @@ class Test_objectstorage_bucket_versioning_enabled: with ( mock.patch( "prowler.providers.common.provider.Provider.get_global_provider", - return_value=set_mocked_oci_provider(), + return_value=set_mocked_oraclecloud_provider(), ), mock.patch( "prowler.providers.oraclecloud.services.objectstorage.objectstorage_bucket_versioning_enabled.objectstorage_bucket_versioning_enabled.objectstorage_client", @@ -227,7 +227,7 @@ class Test_objectstorage_bucket_versioning_enabled: assert fail_results[0].compartment_id is not None # Verify metadata - assert fail_results[0].check_metadata.Provider == "oci" + assert fail_results[0].check_metadata.Provider == "oraclecloud" assert ( fail_results[0].check_metadata.CheckID == "objectstorage_bucket_versioning_enabled" diff --git a/tests/providers/oraclecloud/services/objectstorage/objectstorage_service_test.py b/tests/providers/oraclecloud/services/objectstorage/objectstorage_service_test.py index f4cbe05f87..1000dcea7a 100644 --- a/tests/providers/oraclecloud/services/objectstorage/objectstorage_service_test.py +++ b/tests/providers/oraclecloud/services/objectstorage/objectstorage_service_test.py @@ -1,12 +1,12 @@ from unittest.mock import patch -from tests.providers.oraclecloud.oci_fixtures import set_mocked_oci_provider +from tests.providers.oraclecloud.oci_fixtures import set_mocked_oraclecloud_provider class TestObjectStorageService: def test_service(self): """Test that objectstorage service can be instantiated and mocked""" - oci_provider = set_mocked_oci_provider() + oraclecloud_provider = set_mocked_oraclecloud_provider() # Mock the entire service initialization with patch( @@ -17,14 +17,14 @@ class TestObjectStorageService: ObjectStorage, ) - objectstorage_client = ObjectStorage(oci_provider) + objectstorage_client = ObjectStorage(oraclecloud_provider) # Manually set required attributes since __init__ was mocked objectstorage_client.service = "objectstorage" - objectstorage_client.provider = oci_provider + objectstorage_client.provider = oraclecloud_provider objectstorage_client.audited_compartments = {} objectstorage_client.regional_clients = {} # Verify service name assert objectstorage_client.service == "objectstorage" - assert objectstorage_client.provider == oci_provider + assert objectstorage_client.provider == oraclecloud_provider diff --git a/ui/.husky/pre-commit b/ui/.husky/pre-commit old mode 100644 new mode 100755 index 129b71298f..8e982d4c8a --- a/ui/.husky/pre-commit +++ b/ui/.husky/pre-commit @@ -1 +1,134 @@ -npm run healthcheck +#!/bin/bash + +# Prowler UI - Pre-Commit Hook +# Optionally validates ONLY staged files against AGENTS.md standards using Claude Code +# Controlled by CODE_REVIEW_ENABLED in .env + +set -e + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "🚀 Prowler UI - Pre-Commit Hook" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" + +# Load .env file (look in git root directory) +GIT_ROOT=$(git rev-parse --show-toplevel) +if [ -f "$GIT_ROOT/ui/.env" ]; then + CODE_REVIEW_ENABLED=$(grep "^CODE_REVIEW_ENABLED" "$GIT_ROOT/ui/.env" | cut -d'=' -f2 | tr -d ' ') +elif [ -f "$GIT_ROOT/.env" ]; then + CODE_REVIEW_ENABLED=$(grep "^CODE_REVIEW_ENABLED" "$GIT_ROOT/.env" | cut -d'=' -f2 | tr -d ' ') +elif [ -f ".env" ]; then + CODE_REVIEW_ENABLED=$(grep "^CODE_REVIEW_ENABLED" .env | cut -d'=' -f2 | tr -d ' ') +else + CODE_REVIEW_ENABLED="false" +fi + +# Normalize the value to lowercase +CODE_REVIEW_ENABLED=$(echo "$CODE_REVIEW_ENABLED" | tr '[:upper:]' '[:lower:]') + +echo -e "${BLUE}ℹ️ Code Review Status: ${CODE_REVIEW_ENABLED}${NC}" +echo "" + +# Get staged files (what will be committed) +STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(tsx?|jsx?)$' || true) + +if [ "$CODE_REVIEW_ENABLED" = "true" ]; then + if [ -z "$STAGED_FILES" ]; then + echo -e "${YELLOW}⚠️ No TypeScript/JavaScript files staged to validate${NC}" + echo "" + else + echo -e "${YELLOW}🔍 Running Claude Code standards validation...${NC}" + echo "" + echo -e "${BLUE}📋 Files to validate:${NC}" + echo "$STAGED_FILES" | sed 's/^/ - /' + echo "" + + echo -e "${BLUE}📤 Sending to Claude Code for validation...${NC}" + echo "" + + # Build prompt with git diff of changes AND full context + VALIDATION_PROMPT=$( + cat <<'PROMPT_EOF' +You are a code reviewer for the Prowler UI project. Analyze the code changes (git diff with full context) below and validate they comply with AGENTS.md standards. + +**CRITICAL: You MUST check BOTH the changed lines AND the surrounding context for violations.** + +**RULES TO CHECK:** +1. React Imports: NO `import * as React` or `import React, {` → Use `import { useState }` +2. TypeScript: NO union types like `type X = "a" | "b"` → Use const-based: `const X = {...} as const` +3. Tailwind: NO `var()` or hex colors in className → Use `className="bg-card-bg"` +4. cn(): ONLY for conditionals → NOT for static classes +5. React 19: NO `useMemo`/`useCallback` without reason +6. Zod v4: Use `.min(1)` not `.nonempty()`, `z.email()` not `z.string().email()`. All inputs must be validated with Zod. +7. File Org: 1 feature = local, 2+ features = shared +8. Directives: Server Actions need "use server", clients need "use client" +9. Implement DRY, KISS principles. (example: reusable components, avoid repetition) +10. Layout must work for all the responsive breakpoints (mobile, tablet, desktop) +11. ANY types cannot be used - CRITICAL: Check for `: any` in all visible lines +12. Use the components inside components/shadcn if possible +13. Check Accessibility best practices (like alt tags in images, semantic HTML, Aria labels, etc.) + +=== GIT DIFF WITH CONTEXT === +PROMPT_EOF + ) + + # Add git diff to prompt with more context (U5 = 5 lines before/after) + VALIDATION_PROMPT="$VALIDATION_PROMPT +$(git diff --cached -U5)" + + VALIDATION_PROMPT="$VALIDATION_PROMPT + +=== END DIFF === + +**IMPORTANT: Your response MUST start with exactly one of these lines:** +STATUS: PASSED +STATUS: FAILED + +**If FAILED:** List each violation with File, Line Number, Rule Number, and Issue. +**If PASSED:** Confirm all visible code (including context) complies with AGENTS.md standards. + +**Start your response now with STATUS:**" + + # Send to Claude Code + if VALIDATION_OUTPUT=$(echo "$VALIDATION_PROMPT" | claude 2>&1); then + echo "$VALIDATION_OUTPUT" + echo "" + + # Check result - STRICT MODE: fail if status unclear + if echo "$VALIDATION_OUTPUT" | grep -q "^STATUS: PASSED"; then + echo "" + echo -e "${GREEN}✅ VALIDATION PASSED${NC}" + echo "" + elif echo "$VALIDATION_OUTPUT" | grep -q "^STATUS: FAILED"; then + echo "" + echo -e "${RED}❌ VALIDATION FAILED${NC}" + echo -e "${RED}Fix violations before committing${NC}" + echo "" + exit 1 + else + echo "" + echo -e "${RED}❌ VALIDATION ERROR${NC}" + echo -e "${RED}Could not determine validation status from Claude Code response${NC}" + echo -e "${YELLOW}Response must start with 'STATUS: PASSED' or 'STATUS: FAILED'${NC}" + echo "" + echo -e "${YELLOW}To bypass validation temporarily, set CODE_REVIEW_ENABLED=false in .env${NC}" + echo "" + exit 1 + fi + else + echo -e "${YELLOW}⚠️ Claude Code not available${NC}" + fi + echo "" + fi +else + echo -e "${YELLOW}⏭️ Code review disabled (CODE_REVIEW_ENABLED=false)${NC}" + echo "" +fi diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 325b7ee876..1e4ef29e0a 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -7,6 +7,9 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🚀 Added - RSS feeds support [(#9109)](https://github.com/prowler-cloud/prowler/pull/9109) +- Customer Support menu item [(#9143)](https://github.com/prowler-cloud/prowler/pull/9143) +- IaC (Infrastructure as Code) provider support for scanning remote repositories [(#8751)](https://github.com/prowler-cloud/prowler/pull/8751) +- External resource link to IaC findings for direct navigation to source code in Git repositories [(#9151)](https://github.com/prowler-cloud/prowler/pull/9151) ### 🔄 Changed @@ -19,7 +22,6 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🔄 Changed - Upgrade React to version 19.2.0 [(#9039)](https://github.com/prowler-cloud/prowler/pull/9039) -- Add support for Oracle Cloud Infrastructure (OCI) provider [(#8984)](https://github.com/prowler-cloud/prowler/pull/8984) --- @@ -86,6 +88,8 @@ All notable changes to the **Prowler UI** are documented in this file. - Field-level email validation message [(#8698)](https://github.com/prowler-cloud/prowler/pull/8698) - POST method on auth form [(#8699)](https://github.com/prowler-cloud/prowler/pull/8699) +--- + ## [1.12.0] (Prowler v5.12.0) ### 🚀 Added diff --git a/ui/Dockerfile b/ui/Dockerfile index da920e52fe..234ed10399 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -10,6 +10,7 @@ WORKDIR /app # Install dependencies based on the preferred package manager COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ +COPY scripts ./scripts RUN \ if [ -f package-lock.json ]; then npm install; \ else echo "Lockfile not found." && exit 1; \ diff --git a/ui/README.md b/ui/README.md index 3e334368ff..e0dcb3be33 100644 --- a/ui/README.md +++ b/ui/README.md @@ -87,6 +87,12 @@ You can use one of them `npm`, `yarn`, `pnpm`, `bun`, Example using `npm`: npm install ``` +**Note:** The `npm install` command will automatically configure Git hooks for code quality checks. If you experience issues, you can manually configure them: + +```bash +git config core.hooksPath "ui/.husky" +``` + #### Run the development server ```bash @@ -112,3 +118,48 @@ After modifying the `.npmrc` file, you need to run `pnpm install` again to ensur - [TypeScript](https://www.typescriptlang.org/) - [Framer Motion](https://www.framer.com/motion/) - [next-themes](https://github.com/pacocoursey/next-themes) + +## Git Hooks & Code Review + +This project uses Git hooks to maintain code quality. When you commit changes to TypeScript/JavaScript files, the pre-commit hook can optionally validate them against our coding standards using Claude Code. + +### Enabling Code Review + +To enable automatic code review on commits, add this to your `.env` file in the project root: + +```bash +CODE_REVIEW_ENABLED=true +``` + +When enabled, the hook will: +- ✅ Validate your staged changes against `AGENTS.md` standards +- ✅ Check for common issues (any types, incorrect imports, styling violations, etc.) +- ✅ Block commits that don't comply with the standards +- ✅ Provide helpful feedback on how to fix issues + +### Disabling Code Review + +To disable code review (faster commits, useful for quick iterations): + +```bash +CODE_REVIEW_ENABLED=false +``` + +Or remove the variable from your `.env` file. + +### Requirements + +- [Claude Code CLI](https://github.com/anthropics/claude-code) installed and authenticated +- `.env` file in the project root with `CODE_REVIEW_ENABLED` set + +### Troubleshooting + +If hooks aren't running after commits: + +```bash +# Verify hooks are configured +git config --get core.hooksPath # Should output: ui/.husky + +# Reconfigure if needed +git config core.hooksPath "ui/.husky" +``` diff --git a/ui/actions/overview/index.ts b/ui/actions/overview/index.ts new file mode 100644 index 0000000000..f1246a071c --- /dev/null +++ b/ui/actions/overview/index.ts @@ -0,0 +1,2 @@ +export * from "./overview"; +export * from "./types"; diff --git a/ui/actions/overview/overview.ts b/ui/actions/overview/overview.ts index 28e54befba..0c19f63b08 100644 --- a/ui/actions/overview/overview.ts +++ b/ui/actions/overview/overview.ts @@ -115,3 +115,31 @@ export const getFindingsBySeverity = async ({ return undefined; } }; + +export const getThreatScore = async ({ + filters = {}, +}: { + filters?: Record; +}) => { + const headers = await getAuthHeaders({ contentType: false }); + + const url = new URL(`${apiBaseUrl}/overviews/threatscore`); + + // Handle multiple filters + Object.entries(filters).forEach(([key, value]) => { + if (value !== undefined && value !== null && value !== "") { + url.searchParams.append(key, String(value)); + } + }); + + try { + const response = await fetch(url.toString(), { + headers, + }); + + return handleApiResponse(response); + } catch (error) { + console.error("Error fetching threat score overview:", error); + return undefined; + } +}; diff --git a/ui/actions/overview/types.ts b/ui/actions/overview/types.ts new file mode 100644 index 0000000000..4f82f2da42 --- /dev/null +++ b/ui/actions/overview/types.ts @@ -0,0 +1,60 @@ +// ThreatScore Snapshot Types +// Corresponds to the ThreatScoreSnapshot model from the API + +export interface CriticalRequirement { + requirement_id: string; + risk_level: number; + weight: number; + title: string; +} + +export interface SectionScores { + [sectionName: string]: number; +} + +export interface ThreatScoreSnapshotAttributes { + id: string; + inserted_at: string; + scan: string | null; + provider: string | null; + compliance_id: string; + overall_score: string; // Decimal as string from API + score_delta: string | null; // Decimal as string from API + section_scores: SectionScores; + critical_requirements: CriticalRequirement[]; + total_requirements: number; + passed_requirements: number; + failed_requirements: number; + manual_requirements: number; + total_findings: number; + passed_findings: number; + failed_findings: number; +} + +export interface ThreatScoreSnapshot { + id: string; + type: "threatscore-snapshots"; + attributes: ThreatScoreSnapshotAttributes; +} + +export interface ThreatScoreResponse { + data: ThreatScoreSnapshot[]; +} + +// Filters for ThreatScore endpoint +export interface ThreatScoreFilters { + snapshot_id?: string; + provider_id?: string; + provider_id__in?: string; + provider_type?: string; + provider_type__in?: string; + scan_id?: string; + scan_id__in?: string; + compliance_id?: string; + compliance_id__in?: string; + inserted_at?: string; + inserted_at__gte?: string; + inserted_at__lte?: string; + overall_score__gte?: string; + overall_score__lte?: string; +} diff --git a/ui/actions/providers/providers.ts b/ui/actions/providers/providers.ts index dce72229bd..08e708b19f 100644 --- a/ui/actions/providers/providers.ts +++ b/ui/actions/providers/providers.ts @@ -139,6 +139,24 @@ export const addCredentialsProvider = async (formData: FormData) => { ) as string | undefined; try { + // For IaC provider, fetch the provider data to get the repository URL from uid + if (providerType === "iac") { + const providerUrl = new URL(`${apiBaseUrl}/providers/${providerId}`); + const providerResponse = await fetch(providerUrl.toString(), { + headers: await getAuthHeaders({ contentType: false }), + }); + + if (providerResponse.ok) { + const providerData = await providerResponse.json(); + const providerUid = providerData?.data?.attributes?.uid; + + // Add the repository URL to formData using the provider's uid + if (providerUid) { + formData.append(ProviderCredentialFields.REPOSITORY_URL, providerUid); + } + } + } + const { secretType, secret } = buildSecretConfig( formData, providerType, diff --git a/ui/app/(prowler)/new-overview/components/accounts-selector.tsx b/ui/app/(prowler)/new-overview/components/accounts-selector.tsx index e68edf56ea..210e1f6f6d 100644 --- a/ui/app/(prowler)/new-overview/components/accounts-selector.tsx +++ b/ui/app/(prowler)/new-overview/components/accounts-selector.tsx @@ -8,6 +8,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, OracleCloudProviderBadge, @@ -28,7 +29,8 @@ const PROVIDER_ICON: Record = { kubernetes: , m365: , github: , - oci: , + iac: , + oraclecloud: , }; interface AccountsSelectorProps { diff --git a/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx b/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx index aa1f36dace..a4c3da7b14 100644 --- a/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx +++ b/ui/app/(prowler)/new-overview/components/provider-type-selector.tsx @@ -42,6 +42,11 @@ const GitHubProviderBadge = lazy(() => default: m.GitHubProviderBadge, })), ); +const IacProviderBadge = lazy(() => + import("@/components/icons/providers-badge").then((m) => ({ + default: m.IacProviderBadge, + })), +); const OracleCloudProviderBadge = lazy(() => import("@/components/icons/providers-badge").then((m) => ({ default: m.OracleCloudProviderBadge, @@ -82,7 +87,11 @@ const PROVIDER_DATA: Record< label: "GitHub", icon: GitHubProviderBadge, }, - oci: { + iac: { + label: "Infrastructure as Code", + icon: IacProviderBadge, + }, + oraclecloud: { label: "Oracle Cloud Infrastructure", icon: OracleCloudProviderBadge, }, diff --git a/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx b/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx index 3804441b10..b070a828ba 100644 --- a/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx +++ b/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx @@ -58,7 +58,7 @@ export const RiskSeverityChart = ({ ]; return ( - + Risk Severity diff --git a/ui/app/(prowler)/new-overview/components/status-chart.tsx b/ui/app/(prowler)/new-overview/components/status-chart.tsx index 10b4736aec..7e773f90e7 100644 --- a/ui/app/(prowler)/new-overview/components/status-chart.tsx +++ b/ui/app/(prowler)/new-overview/components/status-chart.tsx @@ -74,7 +74,7 @@ export const StatusChart = ({ ]; return ( - + Check Findings diff --git a/ui/app/(prowler)/new-overview/components/threat-score.tsx b/ui/app/(prowler)/new-overview/components/threat-score.tsx new file mode 100644 index 0000000000..511f6b9d42 --- /dev/null +++ b/ui/app/(prowler)/new-overview/components/threat-score.tsx @@ -0,0 +1,224 @@ +"use client"; + +import { MessageCircleWarning, ThumbsUp } from "lucide-react"; +import Link from "next/link"; + +import type { + CriticalRequirement, + SectionScores, +} from "@/actions/overview/types"; +import { RadialChart } from "@/components/graphs/radial-chart"; +import { + SEVERITY_COLORS, + STATUS_COLORS, +} from "@/components/graphs/shared/constants"; +import { + BaseCard, + CardContent, + CardHeader, + CardTitle, +} from "@/components/shadcn"; + +const THREAT_LEVEL_CONFIG = { + CRITICAL: { + label: "Critical Risk", + color: "text-red-500", + chartColor: SEVERITY_COLORS.Critical, + minScore: 0, + maxScore: 20, + }, + HIGH: { + label: "High Risk", + color: "text-orange-500", + chartColor: SEVERITY_COLORS.High, + minScore: 21, + maxScore: 40, + }, + MODERATE: { + label: "Moderately Secure", + color: "text-yellow-500", + chartColor: SEVERITY_COLORS.Medium, + minScore: 41, + maxScore: 60, + }, + LOW: { + label: "Low Risk", + color: "text-blue-500", + chartColor: SEVERITY_COLORS.Low, + minScore: 61, + maxScore: 80, + }, + SECURE: { + label: "Highly Secure", + color: "text-green-500", + chartColor: STATUS_COLORS.Success, + minScore: 81, + maxScore: 100, + }, +} as const; + +type ThreatLevelKey = keyof typeof THREAT_LEVEL_CONFIG; + +interface ThreatScoreProps { + score?: number | null; + scoreDelta?: number | null; + sectionScores?: SectionScores; + criticalRequirements?: CriticalRequirement[]; + onViewRemediationPlan?: () => void; + className?: string; +} + +function getThreatLevel(score: number): ThreatLevelKey { + for (const [key, config] of Object.entries(THREAT_LEVEL_CONFIG)) { + if (score >= config.minScore && score <= config.maxScore) { + return key as ThreatLevelKey; + } + } + return "MODERATE"; +} + +// Convert section scores to tooltip data for the radial chart +function convertSectionScoresToTooltipData( + sectionScores?: SectionScores, +): Array<{ name: string; value: number; color: string }> { + if (!sectionScores) return []; + + return Object.entries(sectionScores).map(([name, value]) => { + // Determine color based on score value + let color: string = SEVERITY_COLORS.Critical; + if (value >= 80) color = STATUS_COLORS.Success; + else if (value >= 60) color = SEVERITY_COLORS.Low; + else if (value >= 40) color = SEVERITY_COLORS.Medium; + else if (value >= 20) color = SEVERITY_COLORS.High; + + // Round to nearest integer + const roundedValue = Math.round(value); + + return { name, value: roundedValue, color }; + }); +} + +// Extract top gap names from critical requirements +function extractTopGaps( + criticalRequirements?: CriticalRequirement[], + limit = 2, +): string[] { + if (!criticalRequirements || criticalRequirements.length === 0) return []; + + // Sort by risk_level descending, then by weight descending + const sorted = [...criticalRequirements].sort((a, b) => { + if (b.risk_level !== a.risk_level) { + return b.risk_level - a.risk_level; + } + return b.weight - a.weight; + }); + + return sorted.slice(0, limit).map((req) => req.title); +} + +export function ThreatScore({ + score, + scoreDelta, + sectionScores, + criticalRequirements, +}: ThreatScoreProps) { + if (score === null || score === undefined) { + return ( + + + Prowler Threat Score + + +

+ No ThreatScore data available +

+
+
+ ); + } + + const threatLevel = getThreatLevel(score); + const config = THREAT_LEVEL_CONFIG[threatLevel]; + + // Convert section scores to tooltip data + const tooltipData = convertSectionScoresToTooltipData(sectionScores); + + // Extract top gaps from critical requirements + const gaps = extractTopGaps(criticalRequirements, 2); + + return ( + + + Prowler Threat Score + + + + {/* Radial Chart */} +
+
+ +
+ {/* Overlaid Text (centered) */} +
+

+ {config.label} +

+
+
+ + {/* Info Box */} +
+
+ {/* Improvement Message */} + {scoreDelta !== undefined && + scoreDelta !== null && + scoreDelta !== 0 && ( +
+ +

+ Threat score has {scoreDelta > 0 ? "improved" : "decreased"}{" "} + by {Math.abs(scoreDelta)}% +

+
+ )} + + {/* Gaps Message */} + {gaps.length > 0 && ( +
+ +

+ Major gaps include {gaps.slice(0, 2).join(", ")} + {gaps.length > 2 && ` & ${gaps.length - 2} more...`} +

+
+ )} + + {/* View Remediation Plan Button */} +
+ + + View Remediation Plan + + +
+
+
+
+
+ ); +} diff --git a/ui/app/(prowler)/new-overview/page.tsx b/ui/app/(prowler)/new-overview/page.tsx index 3d732fcf85..d45665be0e 100644 --- a/ui/app/(prowler)/new-overview/page.tsx +++ b/ui/app/(prowler)/new-overview/page.tsx @@ -3,6 +3,7 @@ import { Suspense } from "react"; import { getFindingsBySeverity, getFindingsByStatus, + getThreatScore, } from "@/actions/overview/overview"; import { getProviders } from "@/actions/providers"; import { ContentLayout } from "@/components/ui"; @@ -12,6 +13,7 @@ import { AccountsSelector } from "./components/accounts-selector"; import { ProviderTypeSelector } from "./components/provider-type-selector"; import { RiskSeverityChart } from "./components/risk-severity-chart"; import { StatusChart } from "./components/status-chart"; +import { ThreatScore } from "./components/threat-score"; const FILTER_PREFIX = "filter["; @@ -39,7 +41,17 @@ export default async function NewOverviewPage({ -
+
+ +

Loading...

+
+ } + > + + + @@ -143,3 +155,36 @@ const SSRRiskSeverityChart = async ({ /> ); }; + +const SSRThreatScore = async ({ + searchParams, +}: { + searchParams: SearchParamsProps | undefined | null; +}) => { + const filters = pickFilterParams(searchParams); + const threatScoreData = await getThreatScore({ filters }); + + // If no data, pass undefined score and let component handle empty state + if (!threatScoreData?.data || threatScoreData.data.length === 0) { + return ; + } + + // Get the first snapshot (aggregated or single provider) + const snapshot = threatScoreData.data[0]; + const attributes = snapshot.attributes; + + // Parse score from decimal string to number and round to integer + const score = Math.round(parseFloat(attributes.overall_score)); + const scoreDelta = attributes.score_delta + ? Math.round(parseFloat(attributes.score_delta)) + : null; + + return ( + + ); +}; diff --git a/ui/components/filters/custom-provider-inputs.tsx b/ui/components/filters/custom-provider-inputs.tsx index 6a2c5cb078..1ca770157c 100644 --- a/ui/components/filters/custom-provider-inputs.tsx +++ b/ui/components/filters/custom-provider-inputs.tsx @@ -5,6 +5,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, OracleCloudProviderBadge, @@ -64,6 +65,15 @@ export const CustomProviderInputGitHub = () => { ); }; +export const CustomProviderInputIac = () => { + return ( +
+ +

Infrastructure as Code

+
+ ); +}; + export const CustomProviderInputOracleCloud = () => { return (
diff --git a/ui/components/filters/custom-select-provider.tsx b/ui/components/filters/custom-select-provider.tsx index c72830a2a8..5d0e4db52e 100644 --- a/ui/components/filters/custom-select-provider.tsx +++ b/ui/components/filters/custom-select-provider.tsx @@ -11,6 +11,7 @@ import { CustomProviderInputAzure, CustomProviderInputGCP, CustomProviderInputGitHub, + CustomProviderInputIac, CustomProviderInputKubernetes, CustomProviderInputM365, CustomProviderInputOracleCloud, @@ -44,7 +45,11 @@ const providerDisplayData: Record< label: "GitHub", component: , }, - oci: { + iac: { + label: "Infrastructure as Code", + component: , + }, + oraclecloud: { label: "Oracle Cloud Infrastructure", component: , }, diff --git a/ui/components/findings/table/finding-detail.tsx b/ui/components/findings/table/finding-detail.tsx index 432f3a622a..61f7408f3d 100644 --- a/ui/components/findings/table/finding-detail.tsx +++ b/ui/components/findings/table/finding-detail.tsx @@ -1,18 +1,17 @@ "use client"; import { Snippet } from "@heroui/snippet"; +import { Tooltip } from "@heroui/tooltip"; +import { ExternalLink, Link } from "lucide-react"; import ReactMarkdown from "react-markdown"; import { CodeSnippet } from "@/components/ui/code-snippet/code-snippet"; import { CustomSection } from "@/components/ui/custom"; import { CustomLink } from "@/components/ui/custom/custom-link"; -import { - CopyLinkButton, - EntityInfoShort, - InfoField, -} from "@/components/ui/entities"; +import { EntityInfoShort, InfoField } from "@/components/ui/entities"; import { DateWithTime } from "@/components/ui/entities/date-with-time"; import { SeverityBadge } from "@/components/ui/table/severity-badge"; +import { buildGitFileUrl, extractLineRangeFromUid } from "@/lib/iac-utils"; import { FindingProps, ProviderType } from "@/types"; import { Muted } from "../muted"; @@ -60,14 +59,32 @@ export const FindingDetail = ({ params.set("id", findingDetails.id); const url = `${window.location.origin}${currentUrl.pathname}?${params.toString()}`; + // Build Git URL for IaC findings + const gitUrl = + providerDetails.provider === "iac" + ? buildGitFileUrl( + providerDetails.uid, + resource.name, + extractLineRangeFromUid(attributes.uid) || "", + ) + : null; + return (
{/* Header */}
-

+

{renderValue(attributes.check_metadata.checktitle)} - + + +

@@ -238,7 +255,30 @@ export const FindingDetail = ({ {/* Resource Details */} - + + Resource Details + {gitUrl && ( + + + + + + )} + + ) : ( + "Resource Details" + ) + } + >
{renderValue(resource.name)} diff --git a/ui/components/graphs/donut-chart.tsx b/ui/components/graphs/donut-chart.tsx index b2878fd17d..21fefd058b 100644 --- a/ui/components/graphs/donut-chart.tsx +++ b/ui/components/graphs/donut-chart.tsx @@ -181,7 +181,7 @@ export function DonutChart({ -
+
{(item.value > 0 || isEmpty) && (
{ + if (!active || !payload || !payload.length) return null; + + const tooltipItems = payload[0]?.payload?.tooltipData; + if ( + !tooltipItems || + !Array.isArray(tooltipItems) || + tooltipItems.length === 0 + ) + return null; + + return ( +
+
+ {tooltipItems.map((item: TooltipItem, index: number) => ( +
+

+ {item.name} +

+
+

+ {item.value}% +

+
+ ))} +
+
+ ); +}; + export function RadialChart({ percentage, - label = "Score", color = "var(--chart-success-color)", backgroundColor = CHART_COLORS.tooltipBackground, height = 250, @@ -30,14 +74,26 @@ export function RadialChart({ outerRadius = 100, startAngle = 90, endAngle = -270, + hasDots = false, + tooltipData, }: RadialChartProps) { + // Calculate the real barSize based on the difference + const barSize = outerRadius - innerRadius; const data = [ { - name: label, value: percentage, - fill: color, + tooltipData, }, ]; + const middleRadius = innerRadius; + const viewBoxWidth = height; + const viewBoxHeight = height; + const centerX = viewBoxWidth / 2; + const centerY = viewBoxHeight / 2; + const arcAngle = Math.abs(startAngle - endAngle); + const dotSpacing = 20; // 4px dot + 8px space + const arcCircumference = (arcAngle / 360) * (2 * Math.PI * middleRadius); + const numberOfDots = Math.floor(arcCircumference / dotSpacing); return ( @@ -46,7 +102,7 @@ export function RadialChart({ cy="50%" innerRadius={innerRadius} outerRadius={outerRadius} - barSize={20} + barSize={barSize} data={data} startAngle={startAngle} endAngle={endAngle} @@ -57,18 +113,63 @@ export function RadialChart({ angleAxisId={0} tick={false} /> + + {tooltipData && ( + } + wrapperStyle={{ zIndex: 1000 }} + cursor={false} + /> + )} + + + {hasDots && + Array.from({ length: numberOfDots }) + .slice(1, -1) + .map((_, i) => { + // Calculate the angle for this point + // Adjust the index since we now start from 1 + const angleProgress = (i + 1) / (numberOfDots - 1 || 1); + const currentAngle = + startAngle - angleProgress * (startAngle - endAngle); + + // Show dots only in the background part (after the percentage value) + const valueAngleEnd = + startAngle - (percentage / 100) * (startAngle - endAngle); + if (currentAngle > valueAngleEnd) { + return null; // Don't show dots in the part with value + } + + const currentAngleRad = (currentAngle * Math.PI) / 180; + + // Calculate absolute position in the viewBox + const x = centerX + middleRadius * Math.cos(currentAngleRad) + 22; + const y = centerY - middleRadius * Math.sin(currentAngleRad); + + return ( + + ); + })} + = ({ + size, + width, + height, + ...props +}) => ( + +); diff --git a/ui/components/icons/providers-badge/index.ts b/ui/components/icons/providers-badge/index.ts index b143c27d6c..924aa1b6b8 100644 --- a/ui/components/icons/providers-badge/index.ts +++ b/ui/components/icons/providers-badge/index.ts @@ -2,6 +2,7 @@ export * from "./aws-provider-badge"; export * from "./azure-provider-badge"; export * from "./gcp-provider-badge"; export * from "./github-provider-badge"; +export * from "./iac-provider-badge"; export * from "./ks8-provider-badge"; export * from "./m365-provider-badge"; export * from "./oraclecloud-provider-badge"; diff --git a/ui/components/overview/provider-overview/provider-overview.tsx b/ui/components/overview/provider-overview/provider-overview.tsx index fdbd4a81cc..e40dc25494 100644 --- a/ui/components/overview/provider-overview/provider-overview.tsx +++ b/ui/components/overview/provider-overview/provider-overview.tsx @@ -8,6 +8,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, OracleCloudProviderBadge, @@ -38,7 +39,9 @@ export const ProvidersOverview = ({ return ; case "github": return ; - case "oci": + case "iac": + return ; + case "oraclecloud": return ; default: return null; @@ -52,7 +55,8 @@ export const ProvidersOverview = ({ gcp: "GCP", kubernetes: "Kubernetes", github: "GitHub", - oci: "OCI", + iac: "IaC", + oraclecloud: "OCI", }; const providers = PROVIDER_TYPES.map((providerType) => ({ diff --git a/ui/components/providers/enhanced-provider-selector.tsx b/ui/components/providers/enhanced-provider-selector.tsx index 66c07f9a34..3282ede810 100644 --- a/ui/components/providers/enhanced-provider-selector.tsx +++ b/ui/components/providers/enhanced-provider-selector.tsx @@ -17,7 +17,8 @@ const providerTypeLabels: Record = { m365: "Microsoft 365", kubernetes: "Kubernetes", github: "GitHub", - oci: "Oracle Cloud Infrastructure", + iac: "Infrastructure as Code", + oraclecloud: "Oracle Cloud Infrastructure", }; interface EnhancedProviderSelectorProps { diff --git a/ui/components/providers/radio-group-provider.tsx b/ui/components/providers/radio-group-provider.tsx index 7ebfec2a91..3b04cba457 100644 --- a/ui/components/providers/radio-group-provider.tsx +++ b/ui/components/providers/radio-group-provider.tsx @@ -12,6 +12,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, OracleCloudProviderBadge, @@ -79,9 +80,15 @@ export const RadioGroupProvider: React.FC = ({ GitHub
+ +
+ + Infrastructure as Code +
+
diff --git a/ui/components/providers/workflow/forms/base-credentials-form.tsx b/ui/components/providers/workflow/forms/base-credentials-form.tsx index 36cdefbc59..d7835386c9 100644 --- a/ui/components/providers/workflow/forms/base-credentials-form.tsx +++ b/ui/components/providers/workflow/forms/base-credentials-form.tsx @@ -16,6 +16,7 @@ import { AzureCredentials, GCPDefaultCredentials, GCPServiceAccountKey, + IacCredentials, KubernetesCredentials, M365CertificateCredentials, M365ClientSecretCredentials, @@ -34,6 +35,7 @@ import { } from "./select-credentials-type/m365"; import { AzureCredentialsForm } from "./via-credentials/azure-credentials-form"; import { GitHubCredentialsForm } from "./via-credentials/github-credentials-form"; +import { IacCredentialsForm } from "./via-credentials/iac-credentials-form"; import { KubernetesCredentialsForm } from "./via-credentials/k8s-credentials-form"; import { OracleCloudCredentialsForm } from "./via-credentials/oraclecloud-credentials-form"; @@ -160,7 +162,12 @@ export const BaseCredentialsForm = ({ credentialsType={searchParamsObj.get("via") || undefined} /> )} - {providerType === "oci" && ( + {providerType === "iac" && ( + } + /> + )} + {providerType === "oraclecloud" && ( } /> diff --git a/ui/components/providers/workflow/forms/connect-account-form.tsx b/ui/components/providers/workflow/forms/connect-account-form.tsx index f9bf6bafeb..f0ede535bf 100644 --- a/ui/components/providers/workflow/forms/connect-account-form.tsx +++ b/ui/components/providers/workflow/forms/connect-account-form.tsx @@ -51,7 +51,12 @@ const getProviderFieldDetails = (providerType?: ProviderType) => { label: "Username", placeholder: "e.g. your-github-username", }; - case "oci": + case "iac": + return { + label: "Repository URL", + placeholder: "e.g. https://github.com/user/repo", + }; + case "oraclecloud": return { label: "Tenancy OCID", placeholder: "e.g. ocid1.tenancy.oc1..aaaaaaa...", diff --git a/ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx b/ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx new file mode 100644 index 0000000000..e44ea30a1c --- /dev/null +++ b/ui/components/providers/workflow/forms/via-credentials/iac-credentials-form.tsx @@ -0,0 +1,33 @@ +import { Control } from "react-hook-form"; + +import { CustomInput } from "@/components/ui/custom"; +import { IacCredentials } from "@/types"; + +export const IacCredentialsForm = ({ + control, +}: { + control: Control; +}) => { + return ( + <> +
+
+ Connect via Repository +
+
+ Provide an access token if the repository is private (optional). +
+
+ + + ); +}; diff --git a/ui/components/providers/workflow/forms/via-credentials/index.ts b/ui/components/providers/workflow/forms/via-credentials/index.ts index 982e5ca701..daf77c0614 100644 --- a/ui/components/providers/workflow/forms/via-credentials/index.ts +++ b/ui/components/providers/workflow/forms/via-credentials/index.ts @@ -1,3 +1,4 @@ export * from "./azure-credentials-form"; export * from "./github-credentials-form"; +export * from "./iac-credentials-form"; export * from "./k8s-credentials-form"; diff --git a/ui/components/resources/table/resource-detail.tsx b/ui/components/resources/table/resource-detail.tsx index 010cb5447f..e8e118cb91 100644 --- a/ui/components/resources/table/resource-detail.tsx +++ b/ui/components/resources/table/resource-detail.tsx @@ -2,7 +2,8 @@ import { Snippet } from "@heroui/snippet"; import { Spinner } from "@heroui/spinner"; -import { InfoIcon } from "lucide-react"; +import { Tooltip } from "@heroui/tooltip"; +import { ExternalLink, InfoIcon } from "lucide-react"; import { useEffect, useState } from "react"; import { getFindingById } from "@/actions/findings"; @@ -17,6 +18,7 @@ import { } from "@/components/ui/entities"; import { SeverityBadge, StatusFindingBadge } from "@/components/ui/table"; import { createDict } from "@/lib"; +import { buildGitFileUrl } from "@/lib/iac-utils"; import { FindingProps, ProviderType, ResourceProps } from "@/types"; const renderValue = (value: string | null | undefined) => { @@ -162,6 +164,12 @@ export const ResourceDetail = ({ const providerData = resource.relationships.provider.data.attributes; const allFindings = findingsData; + // Build Git URL for IaC resources + const gitUrl = + providerData.provider === "iac" + ? buildGitFileUrl(providerData.uid, attributes.name, "") + : null; + if (selectedFindingId) { const findingTitle = findingDetails?.attributes?.check_metadata?.checktitle || @@ -186,7 +194,30 @@ export const ResourceDetail = ({ return (
{/* Resource Details section */} - + + Resource Details + {gitUrl && ( + + + + + + )} + + ) : ( + "Resource Details" + ) + } + >
diff --git a/ui/components/ui/custom/custom-section.tsx b/ui/components/ui/custom/custom-section.tsx index f7967e0ba1..197bac35c5 100644 --- a/ui/components/ui/custom/custom-section.tsx +++ b/ui/components/ui/custom/custom-section.tsx @@ -1,7 +1,9 @@ +import { type ReactNode } from "react"; + interface CustomSectionProps { - title: string; - children: React.ReactNode; - action?: React.ReactNode; + title: string | ReactNode; + children: ReactNode; + action?: ReactNode; } export const CustomSection = ({ diff --git a/ui/components/ui/entities/copy-link-button.tsx b/ui/components/ui/entities/copy-link-button.tsx deleted file mode 100644 index 1e3d5cdf8b..0000000000 --- a/ui/components/ui/entities/copy-link-button.tsx +++ /dev/null @@ -1,41 +0,0 @@ -"use client"; - -import { Tooltip } from "@heroui/tooltip"; -import { CheckCheck, ExternalLink } from "lucide-react"; -import { useState } from "react"; - -type CopyLinkButtonProps = { - url: string; -}; - -export const CopyLinkButton = ({ url }: CopyLinkButtonProps) => { - const [copied, setCopied] = useState(false); - - const handleCopy = async () => { - try { - await navigator.clipboard.writeText(url); - setCopied(true); - - setTimeout(() => setCopied(false), 500); - } catch (err) { - console.error("Failed to copy URL to clipboard:", err); - } - }; - - return ( - - - - ); -}; diff --git a/ui/components/ui/entities/get-provider-logo.tsx b/ui/components/ui/entities/get-provider-logo.tsx index 7d2f6e5940..918dd30c6c 100644 --- a/ui/components/ui/entities/get-provider-logo.tsx +++ b/ui/components/ui/entities/get-provider-logo.tsx @@ -5,6 +5,7 @@ import { AzureProviderBadge, GCPProviderBadge, GitHubProviderBadge, + IacProviderBadge, KS8ProviderBadge, M365ProviderBadge, OracleCloudProviderBadge, @@ -25,7 +26,9 @@ export const getProviderLogo = (provider: ProviderType) => { return ; case "github": return ; - case "oci": + case "iac": + return ; + case "oraclecloud": return ; default: return null; @@ -46,7 +49,9 @@ export const getProviderName = (provider: ProviderType): string => { return "Microsoft 365"; case "github": return "GitHub"; - case "oci": + case "iac": + return "Infrastructure as Code"; + case "oraclecloud": return "Oracle Cloud Infrastructure"; default: return "Unknown Provider"; diff --git a/ui/components/ui/entities/index.ts b/ui/components/ui/entities/index.ts index bcff63efd9..fb13c99282 100644 --- a/ui/components/ui/entities/index.ts +++ b/ui/components/ui/entities/index.ts @@ -1,4 +1,3 @@ -export * from "./copy-link-button"; export * from "./date-with-time"; export * from "./entity-info-short"; export * from "./get-provider-logo"; diff --git a/ui/docs/code-review/CODE_REVIEW_QUICK_START.md b/ui/docs/code-review/CODE_REVIEW_QUICK_START.md new file mode 100644 index 0000000000..91dd2ad4af --- /dev/null +++ b/ui/docs/code-review/CODE_REVIEW_QUICK_START.md @@ -0,0 +1,115 @@ +# Code Review - Quick Start + +## 3 Steps to Enable + +### 1. Open `.env` +```bash +nano ui/.env +# or your favorite editor +``` + +### 2. Find this line +```bash +CODE_REVIEW_ENABLED=false +``` + +### 3. Change it to +```bash +CODE_REVIEW_ENABLED=true +``` + +**Done! ✅** + +--- + +## What Happens Now + +Every time you `git commit`: + +``` +✅ If your code complies with AGENTS.md standards: + → Commit executes normally + +❌ If there are standard violations: + → Commit is BLOCKED + → You see the errors in the terminal + → Fix the code + → Commit again +``` + +--- + +## Example + +```bash +$ git commit -m "feat: add new component" + +🏁 Prowler UI - Pre-Commit Hook + +ℹ️ Code Review Status: true + +🔍 Running Claude Code standards validation... + +📋 Files to validate: + - components/my-feature.tsx + +📤 Sending to Claude Code for validation... + +STATUS: FAILED +- File: components/my-feature.tsx:45 + Rule: React Imports + Issue: Using 'import * as React' + Expected: import { useState } from "react" + +❌ VALIDATION FAILED +Fix violations before committing + +# Fix the file and commit again +$ git commit -m "feat: add new component" + +🏁 Prowler UI - Pre-Commit Hook + +ℹ️ Code Review Status: true + +🔍 Running Claude Code standards validation... + +✅ VALIDATION PASSED + +# Commit successful ✅ +``` + +--- + +## Disable Temporarily + +If you need to commit without validation: + +```bash +# Option 1: Change in .env +CODE_REVIEW_ENABLED=false + +# Option 2: Bypass (use with caution!) +git commit --no-verify +``` + +--- + +## What Gets Validated + +- ✅ Correct React imports +- ✅ TypeScript patterns (const-based types) +- ✅ Tailwind CSS (no var() or hex in className) +- ✅ cn() utility (only for conditionals) +- ✅ No useMemo/useCallback without reason +- ✅ Zod v4 syntax +- ✅ File organization +- ✅ Directives "use client"/"use server" + +--- + +## More Info + +Read `CODE_REVIEW_SETUP.md` for: +- Troubleshooting +- Complete details +- Advanced configuration diff --git a/ui/docs/code-review/CODE_REVIEW_SETUP.md b/ui/docs/code-review/CODE_REVIEW_SETUP.md new file mode 100644 index 0000000000..7d4d133cf2 --- /dev/null +++ b/ui/docs/code-review/CODE_REVIEW_SETUP.md @@ -0,0 +1,296 @@ +# Code Review Setup - Prowler UI + +Guide to set up automatic code validation with Claude Code in the pre-commit hook. + +## Overview + +The code review system works like this: + +1. **When you enable `CODE_REVIEW_ENABLED=true` in `.env`** + - When you `git commit`, the pre-commit hook runs + - Only validates TypeScript/JavaScript files you're committing + - Uses Claude Code to check if they comply with AGENTS.md + - If there are violations → **BLOCKS the commit** + - If everything is fine → Continues normally + +2. **When `CODE_REVIEW_ENABLED=false` (default)** + - The pre-commit hook does not run validation + - No standards validation + - Developers can commit without restrictions + +## Installation + +### 1. Ensure Claude Code is in your PATH + +```bash +# Verify that claude is available in terminal +which claude + +# If it doesn't appear, check your Claude Code CLI installation +``` + +### 2. Enable validation in `.env` + +In `/ui/.env`, find the "Code Review Configuration" section: + +```bash +#### Code Review Configuration #### +# Enable Claude Code standards validation on pre-commit hook +# Set to 'true' to validate changes against AGENTS.md standards via Claude Code +# Set to 'false' to skip validation +CODE_REVIEW_ENABLED=false # ← Change this to 'true' +``` + +**Options:** +- `CODE_REVIEW_ENABLED=true` → Enables validation +- `CODE_REVIEW_ENABLED=false` → Disables validation (default) + +### 3. The hook is ready + +The `.husky/pre-commit` file already contains the logic. You don't need to install anything else. + +## How It Works + +### Normal Flow (with validation enabled) + +```bash +$ git commit -m "feat: add new component" + +# Pre-commit hook executes automatically +🚀 Prowler UI - Pre-Commit Hook + ℹ️ Code Review Status: true + +📋 Files to validate: + - components/new-feature.tsx + - types/new-feature.ts + +📤 Sending to Claude Code for validation... + +# Claude analyzes the files... + +=== VALIDATION REPORT === +STATUS: PASSED +All files comply with AGENTS.md standards. + +✅ VALIDATION PASSED +# Commit continues ✅ +``` + +### If There Are Violations + +```bash +$ git commit -m "feat: add new component" + +# Claude detects issues... + +=== VALIDATION REPORT === +STATUS: FAILED + +- File: components/new-feature.tsx:15 + Rule: React Imports + Issue: Using 'import * as React' instead of named imports + Expected: import { useState } from "react" + +❌ VALIDATION FAILED + +Please fix the violations before committing: + 1. Review the violations listed above + 2. Fix the code according to AGENTS.md standards + 3. Commit your changes + 4. Try again + +# Commit is BLOCKED ❌ +``` + +## What Gets Validated + +The system verifies that files comply with: + +### 1. React Imports +```typescript +// ❌ WRONG +import * as React from "react" +import React, { useState } from "react" + +// ✅ CORRECT +import { useState } from "react" +``` + +### 2. TypeScript Type Patterns +```typescript +// ❌ WRONG +type SortOption = "high-low" | "low-high" + +// ✅ CORRECT +const SORT_OPTIONS = { + HIGH_LOW: "high-low", + LOW_HIGH: "low-high", +} as const +type SortOption = typeof SORT_OPTIONS[keyof typeof SORT_OPTIONS] +``` + +### 3. Tailwind CSS +```typescript +// ❌ WRONG +className="bg-[var(--color)]" +className="text-[#ffffff]" + +// ✅ CORRECT +className="bg-card-bg text-white" +``` + +### 4. cn() Utility +```typescript +// ❌ WRONG +className={cn("flex items-center")} + +// ✅ CORRECT +className={cn("h-3 w-3", isCircle ? "rounded-full" : "rounded-sm")} +``` + +### 5. React 19 Hooks +```typescript +// ❌ WRONG +const memoized = useMemo(() => value, []) + +// ✅ CORRECT +// Don't use useMemo (React Compiler handles it) +const value = expensiveCalculation() +``` + +### 6. Zod v4 Syntax +```typescript +// ❌ WRONG +z.string().email() +z.string().nonempty() + +// ✅ CORRECT +z.email() +z.string().min(1) +``` + +### 7. File Organization +``` +// ❌ WRONG +Code used by 2+ features in feature-specific folder + +// ✅ CORRECT +Code used by 1 feature → local in that feature +Code used by 2+ features → in shared/global +``` + +### 8. Use Directives +```typescript +// ❌ WRONG +export async function updateUser() { } // Missing "use server" + +// ✅ CORRECT +"use server" +export async function updateUser() { } +``` + +## Disable Temporarily + +If you need to commit without validation temporarily: + +```bash +# Option 1: Change in .env +CODE_REVIEW_ENABLED=false +git commit + +# Option 2: Use git hook bypass +git commit --no-verify + +# Option 3: Disable the hook +chmod -x .husky/pre-commit +git commit +chmod +x .husky/pre-commit +``` + +**⚠️ Note:** `--no-verify` skips ALL hooks. + +## Troubleshooting + +### "Claude Code CLI not found" + +``` +⚠️ Claude Code CLI not found in PATH +To enable: ensure Claude Code is in PATH and CODE_REVIEW_ENABLED=true +``` + +**Solution:** +```bash +# Check where claude-code is installed +which claude-code + +# If not found, add to your ~/.zshrc: +export PATH="$HOME/.local/bin:$PATH" # or where it's installed + +# Reload the terminal +source ~/.zshrc +``` + +### "Validation inconclusive" + +If Claude Code cannot determine the status: + +``` +⚠️ Could not determine validation status +Allowing commit (validation inconclusive) +``` + +The commit is allowed automatically. If you want to be stricter, you can: + +1. Manually review files against AGENTS.md +2. Report the analysis problem to Claude + +### Build fails after validation + +``` +❌ Build failed +``` + +If validation passes but build fails: + +1. Check the build error +2. Fix it locally +3. Commit and try again + +## View the Full Report + +Reports are saved in temporary files that are deleted afterward. To see the detailed report in real-time, watch the hook output: + +```bash +git commit 2>&1 | tee commit-report.txt +``` + +This will save everything to `commit-report.txt`. + +## For the Team + +### Enable on your machine + +```bash +cd ui +# Edit .env locally and set: +CODE_REVIEW_ENABLED=true +``` + +### Recommended Flow + +1. **During development**: `CODE_REVIEW_ENABLED=false` + - Iterate faster + - Build check still runs + +2. **Before final commit**: `CODE_REVIEW_ENABLED=true` + - Verify you meet standards + - Prevent PRs rejected for violations + +3. **In CI/CD**: You could add additional validation + - (future) Server-side validation in GitHub Actions + +## Questions? + +If you have questions about the standards being validated, check: +- `AGENTS.md` - Complete architecture guide +- `CLAUDE.md` - Project-specific instructions diff --git a/ui/docs/code-review/README.md b/ui/docs/code-review/README.md new file mode 100644 index 0000000000..ad546f77f4 --- /dev/null +++ b/ui/docs/code-review/README.md @@ -0,0 +1,241 @@ +# Code Review System Documentation + +Complete documentation for the Claude Code-powered pre-commit validation system. + +## Quick Navigation + +**Want to get started in 3 steps?** +→ Read: [`CODE_REVIEW_QUICK_START.md`](./CODE_REVIEW_QUICK_START.md) + +**Want complete technical details?** +→ Read: [`CODE_REVIEW_SETUP.md`](./CODE_REVIEW_SETUP.md) + +--- + +## What This System Does + +Automatically validates code against AGENTS.md standards when you commit using Claude Code. + +``` +git commit + ↓ +(Optional) Claude Code validation + ↓ +If violations found → Commit is BLOCKED ❌ +If code complies → Commit continues ✅ +``` + +**Key Feature:** Configurable with a single variable in `.env` +- `CODE_REVIEW_ENABLED=true` → Validates (recommended before commits) +- `CODE_REVIEW_ENABLED=false` → Skip validation (default, for iteration) + +--- + +## File Guide + +| File | Purpose | Read Time | +|------|---------|-----------| +| [`CODE_REVIEW_QUICK_START.md`](./CODE_REVIEW_QUICK_START.md) | 3-step setup & examples | 5 min | +| [`CODE_REVIEW_SETUP.md`](./CODE_REVIEW_SETUP.md) | Complete technical guide | 15 min | + +--- + +## What Gets Validated + +When validation is enabled, the system checks: + +✅ **React Imports** +- Must use: `import { useState } from "react"` +- Not: `import * as React` or `import React, {` + +✅ **TypeScript Types** +- Must use: `const STATUS = {...} as const; type Status = typeof STATUS[...]` +- Not: `type Status = "a" | "b"` + +✅ **Tailwind CSS** +- Must use: `className="bg-card-bg text-white"` +- Not: `className="bg-[var(...)]"` or `className="text-[#fff]"` + +✅ **cn() Utility** +- Must use for: `cn("h-3", isActive && "bg-blue")` +- Not for: `cn("static-class")` + +✅ **React 19 Hooks** +- No: `useMemo()` / `useCallback()` without documented reason +- Use: Nothing (React Compiler handles optimization) + +✅ **Zod v4 Syntax** +- Must use: `z.email()`, `.min(1)` +- Not: `z.string().email()`, `.nonempty()` + +✅ **File Organization** +- 1 feature uses → Keep local in feature folder +- 2+ features use → Move to shared/global + +✅ **Directives** +- Server Actions must have: `"use server"` +- Client Components must have: `"use client"` + +--- + +## Installation (For Your Team) + +### Step 1: Decide if you want validation +- **Optional:** Each developer decides +- **Team policy:** Consider making it standard before commits + +### Step 2: Enable in your environment +```bash +# Edit ui/.env +CODE_REVIEW_ENABLED=true +``` + +### Step 3: Done! +Your next `git commit` will validate automatically. + +--- + +## Support + +| Question | Answer | +|----------|--------| +| How do I enable it? | Change `CODE_REVIEW_ENABLED=true` in `.env` | +| How do I disable it? | Change `CODE_REVIEW_ENABLED=false` in `.env` | +| How do I bypass? | Use `git commit --no-verify` (emergency only) | +| What if Claude Code isn't found? | Check PATH: `which claude` | +| What if hook doesn't run? | Check executable: `chmod +x .husky/pre-commit` | +| How do I test it? | Enable validation and commit code with violations to test | +| What if I don't have Claude Code? | Validation is skipped gracefully | + +--- + +## Key Features + +✅ **No Setup Required** +- Uses Claude Code already in your PATH +- No API keys needed +- Works offline (if Claude Code supports it) + +✅ **Smart Validation** +- Only checks files being committed +- Not the entire codebase +- Fast: ~10-30 seconds with validation enabled + +✅ **Flexible** +- Can be enabled/disabled per developer +- Can be disabled temporarily with `git commit --no-verify` +- Default is disabled (doesn't interrupt workflow) + +✅ **Clear Feedback** +- Shows exactly what violates standards +- Shows file:line references +- Explains how to fix each issue + +✅ **Well Documented** +- 5 different documentation files +- For different needs and levels +- Examples and troubleshooting included + +--- + +## Architecture + +``` +┌─────────────────────────────────────────┐ +│ Developer commits code │ +└────────────────┬────────────────────────┘ + ↓ + ┌─────────────────┐ + │ Pre-Commit Hook │ + │ (.husky/pre-commit) + └────────┬────────┘ + ↓ + Read CODE_REVIEW_ENABLED from .env + ↓ + ┌──────────────────────────┐ + │ If false (disabled) │ + └────────┬─────────────────┘ + ↓ + exit 0 (OK) + ↓ + Commit continues ✅ + + ┌──────────────────────────┐ + │ If true (enabled) │ + └────────┬─────────────────┘ + ↓ + Extract staged files + (git diff --cached) + ↓ + Build prompt with git diff + ↓ + Send to: claude < prompt + ↓ + Analyze against AGENTS.md + ↓ + Return: STATUS: PASSED or FAILED + ↓ + Parse with: grep "^STATUS:" + ↓ + ┌──────────────────┐ + │ PASSED detected │ + └────────┬─────────┘ + ↓ + exit 0 (OK) + ↓ + Commit continues ✅ + + ┌──────────────────┐ + │ FAILED detected │ + └────────┬─────────┘ + ↓ + Show violations + ↓ + exit 1 (FAIL) + ↓ + Commit is BLOCKED ❌ + ↓ + Developer fixes code + Developer commits again +``` + +--- + +## Getting Started + +1. **Read:** [`CODE_REVIEW_QUICK_START.md`](./CODE_REVIEW_QUICK_START.md) (5 minutes) +2. **Enable:** Set `CODE_REVIEW_ENABLED=true` in your `ui/.env` +3. **Test:** Commit some code and see validation in action +4. **For help:** See the troubleshooting section in [`CODE_REVIEW_SETUP.md`](./CODE_REVIEW_SETUP.md) + +--- + +## Implementation Details + +- **Files Modified:** 1 (`.husky/pre-commit`) +- **Files Created:** 3 (documentation) +- **Hook Size:** ~120 lines of bash +- **Dependencies:** Claude Code CLI (already available) +- **Setup Time:** 1 minute +- **Default:** Disabled (no workflow interruption) + +--- + +## Questions? + +- **How to enable?** → `CODE_REVIEW_QUICK_START.md` +- **How does it work?** → `CODE_REVIEW_SETUP.md` +- **Troubleshooting?** → See troubleshooting section in `CODE_REVIEW_SETUP.md` + +--- + +## Status + +✅ **Ready to Use** + +The system is fully implemented, documented, and tested. You can enable it immediately with a single variable change. + +--- + +**Last Updated:** November 6, 2024 +**Status:** Complete Implementation diff --git a/ui/hooks/use-credentials-form.ts b/ui/hooks/use-credentials-form.ts index 01b7c60fef..a9a6215ba3 100644 --- a/ui/hooks/use-credentials-form.ts +++ b/ui/hooks/use-credentials-form.ts @@ -157,7 +157,7 @@ export const useCredentialsForm = ({ }; } return baseDefaults; - case "oci": + case "oraclecloud": return { ...baseDefaults, [ProviderCredentialFields.OCI_USER]: "", diff --git a/ui/lib/external-urls.ts b/ui/lib/external-urls.ts index 6df7753856..9a7385ecce 100644 --- a/ui/lib/external-urls.ts +++ b/ui/lib/external-urls.ts @@ -32,10 +32,15 @@ export const getProviderHelpText = (provider: string) => { text: "Need help connecting your GitHub account?", link: "https://goto.prowler.com/provider-github", }; - case "oci": + case "iac": + return { + text: "Need help scanning your Infrastructure as Code repository?", + link: "https://goto.prowler.com/provider-iac", + }; + case "oraclecloud": return { text: "Need help connecting your Oracle Cloud account?", - link: "https://goto.prowler.com/provider-oci", + link: "https://goto.prowler.com/provider-oraclecloud", }; default: return { diff --git a/ui/lib/iac-utils.ts b/ui/lib/iac-utils.ts new file mode 100644 index 0000000000..ea9ffa47d8 --- /dev/null +++ b/ui/lib/iac-utils.ts @@ -0,0 +1,188 @@ +/** + * Extracts line range from a Finding UID + * Finding UID format: {CheckID}-{resource_name}-{line_range} + * Example: "AVD-AWS-0001-main.tf-10:15" -> "10:15" + * + * @param findingUid - The finding UID + * @returns Line range string or null if not found + */ +export function extractLineRangeFromUid(findingUid: string): string | null { + if (!findingUid) { + return null; + } + + // Split by dash and get the last part (line range) + const parts = findingUid.split("-"); + const lastPart = parts[parts.length - 1]; + + // Check if the last part is a line range in format "number:number" + // This ensures we don't confuse numeric filenames with line ranges + if (/^\d+:\d+$/.test(lastPart)) { + return lastPart; + } + + return null; +} + +/** + * Builds a Git repository URL with file path and line numbers + * Supports GitHub, GitLab, Bitbucket, and generic Git URLs + * + * @param repoUrl - Repository URL (can be HTTPS or git@ format) + * @param filePath - Path to the file in the repository + * @param lineRange - Line range in format "10-15" or "10:15" or "10" + * @returns Complete URL to the file with line numbers, or null if URL cannot be built + */ +export function buildGitFileUrl( + repoUrl: string, + filePath: string, + lineRange: string, +): string | null { + if (!repoUrl || !filePath) { + return null; + } + + try { + // Normalize the repository URL + let normalizedUrl = repoUrl.trim(); + + // Convert git@ format to HTTPS (best effort) + if (normalizedUrl.startsWith("git@")) { + // git@github.com:user/repo.git -> https://github.com/user/repo + normalizedUrl = normalizedUrl + .replace(/^git@/, "https://") + .replace(/\.git$/, "") + .replace(/:([^:]+)$/, "/$1"); // Replace last : with / + } + + // Remove .git suffix if present + normalizedUrl = normalizedUrl.replace(/\.git$/, ""); + + // Parse URL to determine provider + const url = new URL(normalizedUrl); + const hostname = url.hostname.toLowerCase(); + + // Clean up file path (remove leading slashes) + const cleanFilePath = filePath.replace(/^\/+/, ""); + + // Parse line range + const { startLine, endLine } = parseLineRange(lineRange); + + // Build URL based on Git provider + if (hostname.includes("github")) { + return buildGitHubUrl(normalizedUrl, cleanFilePath, startLine, endLine); + } else if (hostname.includes("gitlab")) { + return buildGitLabUrl(normalizedUrl, cleanFilePath, startLine, endLine); + } else if (hostname.includes("bitbucket")) { + return buildBitbucketUrl( + normalizedUrl, + cleanFilePath, + startLine, + endLine, + ); + } else { + // Generic Git provider - try GitHub format as fallback + return buildGitHubUrl(normalizedUrl, cleanFilePath, startLine, endLine); + } + } catch (error) { + console.error("Error building Git file URL:", error); + return null; + } +} + +/** + * Parses line range string into start and end line numbers + */ +function parseLineRange(lineRange: string): { + startLine: number | null; + endLine: number | null; +} { + if (!lineRange || lineRange === "file") { + return { startLine: null, endLine: null }; + } + + // Handle formats: "10-15", "10:15", "10" + // Safe regex: anchored pattern for line numbers only (no ReDoS risk) + // eslint-disable-next-line security/detect-unsafe-regex + const match = lineRange.match(/^(\d+)[-:]?(\d+)?$/); + if (match) { + const startLine = parseInt(match[1], 10); + const endLine = match[2] ? parseInt(match[2], 10) : startLine; + return { startLine, endLine }; + } + + return { startLine: null, endLine: null }; +} + +/** + * Builds GitHub-style URL + * Format: https://github.com/user/repo/blob/main/path/file.tf#L10-L15 + */ +function buildGitHubUrl( + baseUrl: string, + filePath: string, + startLine: number | null, + endLine: number | null, +): string { + // Assume main/master branch for simplicity + const branch = "main"; + let url = `${baseUrl}/blob/${branch}/${filePath}`; + + if (startLine !== null) { + if (endLine !== null && endLine !== startLine) { + url += `#L${startLine}-L${endLine}`; + } else { + url += `#L${startLine}`; + } + } + + return url; +} + +/** + * Builds GitLab-style URL + * Format: https://gitlab.com/user/repo/-/blob/main/path/file.tf#L10-15 + */ +function buildGitLabUrl( + baseUrl: string, + filePath: string, + startLine: number | null, + endLine: number | null, +): string { + const branch = "main"; + let url = `${baseUrl}/-/blob/${branch}/${filePath}`; + + if (startLine !== null) { + if (endLine !== null && endLine !== startLine) { + url += `#L${startLine}-${endLine}`; + } else { + url += `#L${startLine}`; + } + } + + return url; +} + +/** + * Builds Bitbucket-style URL + * Format: https://bitbucket.org/user/repo/src/main/path/file.tf#lines-10:15 + */ +function buildBitbucketUrl( + baseUrl: string, + filePath: string, + startLine: number | null, + endLine: number | null, +): string { + const branch = "main"; + let url = `${baseUrl}/src/${branch}/${filePath}`; + + if (startLine !== null) { + if (endLine !== null && endLine !== startLine) { + url += `#lines-${startLine}:${endLine}`; + } else { + url += `#lines-${startLine}`; + } + } + + return url; +} diff --git a/ui/lib/menu-list.ts b/ui/lib/menu-list.ts index e2e83f0951..c2f7ff6f34 100644 --- a/ui/lib/menu-list.ts +++ b/ui/lib/menu-list.ts @@ -5,6 +5,7 @@ import { Group, LayoutGrid, Mail, + MessageCircleQuestion, Puzzle, Settings, ShieldCheck, @@ -25,7 +26,6 @@ import { APIdocIcon, AWSIcon, AzureIcon, - CircleHelpIcon, DocIcon, GCPIcon, GithubIcon, @@ -250,11 +250,17 @@ export const getMenuList = ({ label: "API reference", icon: APIdocIcon, }, + { + href: "https://customer.support.prowler.com/servicedesk/customer/portal/9/create/102", + target: "_blank", + label: "Customer Support", + icon: MessageCircleQuestion, + }, { href: "https://github.com/prowler-cloud/prowler/issues", target: "_blank", - label: "Support", - icon: CircleHelpIcon, + label: "Community Support", + icon: GithubIcon, }, ], defaultOpen: false, diff --git a/ui/lib/provider-credentials/build-crendentials.ts b/ui/lib/provider-credentials/build-crendentials.ts index 059f1a91d9..4972b5a7e0 100644 --- a/ui/lib/provider-credentials/build-crendentials.ts +++ b/ui/lib/provider-credentials/build-crendentials.ts @@ -197,6 +197,20 @@ export const buildGitHubSecret = (formData: FormData) => { return {}; }; +export const buildIacSecret = (formData: FormData) => { + const secret = { + [ProviderCredentialFields.REPOSITORY_URL]: getFormValue( + formData, + ProviderCredentialFields.REPOSITORY_URL, + ), + [ProviderCredentialFields.ACCESS_TOKEN]: getFormValue( + formData, + ProviderCredentialFields.ACCESS_TOKEN, + ), + }; + return filterEmptyValues(secret); +}; + /** * Utility function to safely encode a string to base64 * Handles UTF-8 characters properly without using deprecated APIs @@ -286,7 +300,11 @@ export const buildSecretConfig = ( secretType: "static", secret: buildGitHubSecret(formData), }), - oci: () => ({ + iac: () => ({ + secretType: "static", + secret: buildIacSecret(formData), + }), + oraclecloud: () => ({ secretType: "static", secret: buildOracleCloudSecret(formData, providerUid), }), diff --git a/ui/lib/provider-credentials/provider-credential-fields.ts b/ui/lib/provider-credentials/provider-credential-fields.ts index c60ecf3298..43b2db6f93 100644 --- a/ui/lib/provider-credentials/provider-credential-fields.ts +++ b/ui/lib/provider-credentials/provider-credential-fields.ts @@ -45,6 +45,10 @@ export const ProviderCredentialFields = { GITHUB_APP_ID: "github_app_id", GITHUB_APP_KEY: "github_app_key_content", + // IaC fields + REPOSITORY_URL: "repository_url", + ACCESS_TOKEN: "access_token", + // OCI fields OCI_USER: "user", OCI_FINGERPRINT: "fingerprint", @@ -81,6 +85,8 @@ export const ErrorPointers = { OAUTH_APP_TOKEN: "/data/attributes/secret/oauth_app_token", GITHUB_APP_ID: "/data/attributes/secret/github_app_id", GITHUB_APP_KEY: "/data/attributes/secret/github_app_key_content", + REPOSITORY_URL: "/data/attributes/secret/repository_url", + ACCESS_TOKEN: "/data/attributes/secret/access_token", CERTIFICATE_CONTENT: "/data/attributes/secret/certificate_content", OCI_USER: "/data/attributes/secret/user", OCI_FINGERPRINT: "/data/attributes/secret/fingerprint", diff --git a/ui/package.json b/ui/package.json index db33a08fac..e89a07c1bf 100644 --- a/ui/package.json +++ b/ui/package.json @@ -7,7 +7,7 @@ "start": "next start", "start:standalone": "node .next/standalone/server.js", "deps:log": "node scripts/update-dependency-log.js", - "postinstall": "node -e \"const fs=require('fs'); if(fs.existsSync('scripts/update-dependency-log.js')) require('./scripts/update-dependency-log.js'); else console.log('skip deps:log (script missing)');\"", + "postinstall": "node scripts/postinstall.js", "typecheck": "tsc", "healthcheck": "npm run typecheck && npm run lint:check", "lint:check": "eslint . --ext .ts,.tsx -c .eslintrc.cjs", diff --git a/ui/scripts/postinstall.js b/ui/scripts/postinstall.js new file mode 100644 index 0000000000..d545707178 --- /dev/null +++ b/ui/scripts/postinstall.js @@ -0,0 +1,32 @@ +#!/usr/bin/env node + +/** + * Post-install script for Prowler UI + * + * This script runs after npm install to: + * 1. Update dependency log (if the script exists) + * 2. Setup git hooks (if the script exists) + */ + +const fs = require("fs"); +const path = require("path"); + +function runScriptIfExists(scriptPath, scriptName) { + const fullPath = path.join(__dirname, scriptPath); + + if (fs.existsSync(fullPath)) { + try { + require(fullPath); + } catch (error) { + console.warn(`⚠️ Error running ${scriptName}:`, error.message); + } + } else { + console.log(`Skip ${scriptName} (script missing)`); + } +} + +// Run dependency log update +runScriptIfExists("./update-dependency-log.js", "deps:log"); + +// Run git hooks setup +runScriptIfExists("./setup-git-hooks.js", "setup-git-hooks"); diff --git a/ui/scripts/setup-git-hooks.js b/ui/scripts/setup-git-hooks.js new file mode 100755 index 0000000000..a3f219813f --- /dev/null +++ b/ui/scripts/setup-git-hooks.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +/** + * Setup Git Hooks for Prowler UI + * + * This script configures Git to use Husky hooks located in ui/.husky + * It runs automatically after npm install via the postinstall script. + */ + +const { execSync } = require('child_process'); +const path = require('path'); + +try { + // Get the git root directory + const gitRoot = execSync('git rev-parse --show-toplevel', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'] + }).trim(); + + // Check if we're in a git repository + if (!gitRoot) { + console.log('⚠️ Not in a git repository. Skipping git hooks setup.'); + process.exit(0); + } + + // Get current hooks path + let currentHooksPath; + try { + currentHooksPath = execSync('git config --get core.hooksPath', { + encoding: 'utf8', + stdio: ['pipe', 'pipe', 'pipe'] + }).trim(); + } catch { + // core.hooksPath not set yet + currentHooksPath = null; + } + + const expectedHooksPath = 'ui/.husky'; + + // Only configure if not already set correctly + if (currentHooksPath !== expectedHooksPath) { + execSync(`git config core.hooksPath "${expectedHooksPath}"`, { + stdio: 'inherit' + }); + console.log('✅ Git hooks configured: core.hooksPath = ui/.husky'); + } else { + console.log('✅ Git hooks already configured correctly'); + } + +} catch (error) { + // Don't fail the installation if git hooks setup fails + console.warn('⚠️ Could not setup git hooks:', error.message); + console.warn(' You may need to run manually: git config core.hooksPath "ui/.husky"'); +} diff --git a/ui/tailwind.config.js b/ui/tailwind.config.js index fedd8da682..d9f032ada8 100644 --- a/ui/tailwind.config.js +++ b/ui/tailwind.config.js @@ -4,9 +4,10 @@ const { heroui } = require("@heroui/theme"); module.exports = { darkMode: ["class"], content: [ - "./components/**/*.{ts,jsx,tsx,mdx}", - "./app/**/*.{ts,jsx,tsx,mdx}", + "./components/**/*.{ts,jsx,tsx}", + "./app/**/*.{ts,jsx,tsx}", "./node_modules/@heroui/theme/dist/**/*.{js,ts,jsx,tsx}", + "!./docs/**/*", ], prefix: "", theme: { diff --git a/ui/types/components.ts b/ui/types/components.ts index 21dfeccf79..83544aed40 100644 --- a/ui/types/components.ts +++ b/ui/types/components.ts @@ -248,6 +248,12 @@ export type KubernetesCredentials = { [ProviderCredentialFields.PROVIDER_ID]: string; }; +export type IacCredentials = { + [ProviderCredentialFields.REPOSITORY_URL]: string; + [ProviderCredentialFields.ACCESS_TOKEN]?: string; + [ProviderCredentialFields.PROVIDER_ID]: string; +}; + export type OCICredentials = { [ProviderCredentialFields.OCI_USER]: string; [ProviderCredentialFields.OCI_FINGERPRINT]: string; @@ -264,6 +270,7 @@ export type CredentialsFormSchema = | GCPDefaultCredentials | GCPServiceAccountKey | KubernetesCredentials + | IacCredentials | M365Credentials | OCICredentials; diff --git a/ui/types/formSchemas.ts b/ui/types/formSchemas.ts index f4966fe36d..a0d073d3a4 100644 --- a/ui/types/formSchemas.ts +++ b/ui/types/formSchemas.ts @@ -111,7 +111,12 @@ export const addProviderFormSchema = z providerUid: z.string(), }), z.object({ - providerType: z.literal("oci"), + providerType: z.literal("iac"), + [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), + providerUid: z.string(), + }), + z.object({ + providerType: z.literal("oraclecloud"), [ProviderCredentialFields.PROVIDER_ALIAS]: z.string(), providerUid: z.string(), }), @@ -196,28 +201,37 @@ export const addCredentialsFormSchema = ( .string() .optional(), } - : providerType === "oci" + : providerType === "iac" ? { - [ProviderCredentialFields.OCI_USER]: z + [ProviderCredentialFields.REPOSITORY_URL]: z .string() - .min(1, "User OCID is required"), - [ProviderCredentialFields.OCI_FINGERPRINT]: z + .optional(), + [ProviderCredentialFields.ACCESS_TOKEN]: z .string() - .min(1, "Fingerprint is required"), - [ProviderCredentialFields.OCI_KEY_CONTENT]: z - .string() - .min(1, "Private Key Content is required"), - [ProviderCredentialFields.OCI_TENANCY]: z - .string() - .min(1, "Tenancy OCID is required"), - [ProviderCredentialFields.OCI_REGION]: z - .string() - .min(1, "Region is required"), - [ProviderCredentialFields.OCI_PASS_PHRASE]: z - .union([z.string(), z.literal("")]) .optional(), } - : {}), + : providerType === "oraclecloud" + ? { + [ProviderCredentialFields.OCI_USER]: z + .string() + .min(1, "User OCID is required"), + [ProviderCredentialFields.OCI_FINGERPRINT]: z + .string() + .min(1, "Fingerprint is required"), + [ProviderCredentialFields.OCI_KEY_CONTENT]: z + .string() + .min(1, "Private Key Content is required"), + [ProviderCredentialFields.OCI_TENANCY]: z + .string() + .min(1, "Tenancy OCID is required"), + [ProviderCredentialFields.OCI_REGION]: z + .string() + .min(1, "Region is required"), + [ProviderCredentialFields.OCI_PASS_PHRASE]: z + .union([z.string(), z.literal("")]) + .optional(), + } + : {}), }) .superRefine((data: Record, ctx) => { if (providerType === "m365") { diff --git a/ui/types/providers.ts b/ui/types/providers.ts index 658101c1ed..adbc717ccd 100644 --- a/ui/types/providers.ts +++ b/ui/types/providers.ts @@ -5,7 +5,8 @@ export const PROVIDER_TYPES = [ "kubernetes", "m365", "github", - "oci", + "iac", + "oraclecloud", ] as const; export type ProviderType = (typeof PROVIDER_TYPES)[number];