mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-04-09 11:17:08 +00:00
Compare commits
4 Commits
chore/prek
...
PROWLER-12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e128725d9 | ||
|
|
89fe867944 | ||
|
|
2be2753c55 | ||
|
|
283259f34c |
4
.github/workflows/sdk-tests.yml
vendored
4
.github/workflows/sdk-tests.yml
vendored
@@ -216,11 +216,11 @@ jobs:
|
||||
echo "AWS service_paths='${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}'"
|
||||
|
||||
if [ "${STEPS_AWS_SERVICES_OUTPUTS_RUN_ALL}" = "true" ]; then
|
||||
poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml tests/providers/aws
|
||||
poetry run pytest -p no:randomly -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml tests/providers/aws
|
||||
elif [ -z "${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}" ]; then
|
||||
echo "No AWS service paths detected; skipping AWS tests."
|
||||
else
|
||||
poetry run pytest -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml ${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}
|
||||
poetry run pytest -p no:randomly -n auto --cov=./prowler/providers/aws --cov-report=xml:aws_coverage.xml ${STEPS_AWS_SERVICES_OUTPUTS_SERVICE_PATHS}
|
||||
fi
|
||||
env:
|
||||
STEPS_AWS_SERVICES_OUTPUTS_RUN_ALL: ${{ steps.aws-services.outputs.run_all }}
|
||||
|
||||
@@ -153,12 +153,12 @@ Prowler is an open-source cloud security assessment tool supporting AWS, Azure,
|
||||
```bash
|
||||
# Setup
|
||||
poetry install --with dev
|
||||
poetry run prek install
|
||||
poetry run pre-commit install
|
||||
|
||||
# Code quality
|
||||
poetry run make lint
|
||||
poetry run make format
|
||||
poetry run prek run --all-files
|
||||
poetry run pre-commit run --all-files
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -246,7 +246,14 @@ Some pre-commit hooks require tools installed on your system:
|
||||
|
||||
1. **Install [TruffleHog](https://github.com/trufflesecurity/trufflehog#install)** (secret scanning) — see the [official installation options](https://github.com/trufflesecurity/trufflehog#install).
|
||||
|
||||
2. **Install [Hadolint](https://github.com/hadolint/hadolint#install)** (Dockerfile linting) — see the [official installation options](https://github.com/hadolint/hadolint#install).
|
||||
2. **Install [Safety](https://github.com/pyupio/safety)** (dependency vulnerability checking):
|
||||
|
||||
```console
|
||||
# Requires a Python environment (e.g. via pyenv)
|
||||
pip install safety
|
||||
```
|
||||
|
||||
3. **Install [Hadolint](https://github.com/hadolint/hadolint#install)** (Dockerfile linting) — see the [official installation options](https://github.com/hadolint/hadolint#install).
|
||||
|
||||
## Prowler CLI
|
||||
### Pip package
|
||||
|
||||
@@ -118,22 +118,18 @@ In case you have any doubts, consult the [Poetry environment activation guide](h
|
||||
|
||||
### Pre-Commit Hooks
|
||||
|
||||
This repository uses Git pre-commit hooks managed by the [prek](https://prek.j178.dev/) tool, it is installed with `poetry install --with dev`. Next, run the following command in the root of this repository:
|
||||
This repository uses Git pre-commit hooks managed by the [pre-commit](https://pre-commit.com/) tool, it is installed with `poetry install --with dev`. Next, run the following command in the root of this repository:
|
||||
|
||||
```shell
|
||||
prek install
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
Successful installation should produce the following output:
|
||||
|
||||
```shell
|
||||
prek installed at `.git/hooks/pre-commit`
|
||||
pre-commit installed at .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
<Warning>
|
||||
If pre-commit hooks were previously installed, run `prek install --overwrite` to replace the existing hook. Otherwise, both tools will run on each commit.
|
||||
</Warning>
|
||||
|
||||
### Code Quality and Security Checks
|
||||
|
||||
Before merging pull requests, several automated checks and utilities ensure code security and updated dependencies:
|
||||
|
||||
BIN
docs/images/providers/select-vercel-prowler-cloud.png
Normal file
BIN
docs/images/providers/select-vercel-prowler-cloud.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
BIN
docs/images/providers/vercel-launch-scan.png
Normal file
BIN
docs/images/providers/vercel-launch-scan.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 81 KiB |
BIN
docs/images/providers/vercel-team-id-form.png
Normal file
BIN
docs/images/providers/vercel-team-id-form.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
docs/images/providers/vercel-token-form.png
Normal file
BIN
docs/images/providers/vercel-token-form.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 90 KiB |
@@ -13,9 +13,63 @@ Set up authentication for Vercel with the [Vercel Authentication](/user-guide/pr
|
||||
- Create a Vercel API Token with access to the target team
|
||||
- Identify the Team ID (optional, required to scope the scan to a single team)
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Prowler Cloud" icon="cloud" href="#prowler-cloud">
|
||||
Onboard Vercel using Prowler Cloud
|
||||
</Card>
|
||||
<Card title="Prowler CLI" icon="terminal" href="#prowler-cli">
|
||||
Onboard Vercel using Prowler CLI
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Prowler Cloud
|
||||
|
||||
<VersionBadge version="5.23.0" />
|
||||
|
||||
### Step 1: Add the Provider
|
||||
|
||||
1. Go to [Prowler Cloud](https://cloud.prowler.com/) or launch [Prowler App](/user-guide/tutorials/prowler-app).
|
||||
2. Navigate to "Configuration" > "Cloud Providers".
|
||||
|
||||

|
||||
|
||||
3. Click "Add Cloud Provider".
|
||||
|
||||

|
||||
|
||||
4. Select "Vercel".
|
||||
|
||||

|
||||
|
||||
5. Enter the **Team ID** and an optional alias, then click "Next".
|
||||
|
||||

|
||||
|
||||
<Note>
|
||||
The Team ID can be found in the Vercel Dashboard under "Settings" > "General". It follows the format `team_xxxxxxxxxxxxxxxxxxxx`. For detailed instructions, see the [Authentication guide](/user-guide/providers/vercel/authentication).
|
||||
</Note>
|
||||
|
||||
### Step 2: Provide Credentials
|
||||
|
||||
1. Enter the **API Token** created in the Vercel Dashboard.
|
||||
|
||||

|
||||
|
||||
For the complete token creation workflow, follow the [Authentication guide](/user-guide/providers/vercel/authentication#api-token).
|
||||
|
||||
### Step 3: Launch the Scan
|
||||
|
||||
1. Review the connection summary.
|
||||
2. Choose the scan schedule: run a single scan or set up daily scans (every 24 hours).
|
||||
3. Click **Launch Scan** to start auditing Vercel.
|
||||
|
||||

|
||||
|
||||
---
|
||||
|
||||
## Prowler CLI
|
||||
|
||||
<VersionBadge version="5.22.0" />
|
||||
<VersionBadge version="5.23.0" />
|
||||
|
||||
### Step 1: Set Up Authentication
|
||||
|
||||
|
||||
118
poetry.lock
generated
118
poetry.lock
generated
@@ -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.1.4 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "about-time"
|
||||
@@ -808,7 +808,7 @@ description = "Timeout context manager for asyncio programs"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["main"]
|
||||
markers = "python_version < \"3.11\""
|
||||
markers = "python_version == \"3.10\""
|
||||
files = [
|
||||
{file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"},
|
||||
{file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"},
|
||||
@@ -1671,6 +1671,18 @@ files = [
|
||||
[package.dependencies]
|
||||
pycparser = {version = "*", markers = "implementation_name != \"PyPy\""}
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.4.0"
|
||||
description = "Validate configuration and produce human readable error messages."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfn-lint"
|
||||
version = "1.38.0"
|
||||
@@ -2168,6 +2180,18 @@ files = [
|
||||
graph = ["objgraph (>=1.7.2)"]
|
||||
profile = ["gprof2dot (>=2022.7.29)"]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.4.0"
|
||||
description = "Distribution utilities"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16"},
|
||||
{file = "distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distro"
|
||||
version = "1.9.0"
|
||||
@@ -2355,7 +2379,7 @@ description = "Backport of PEP 654 (exception groups)"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
groups = ["main", "dev"]
|
||||
markers = "python_version < \"3.11\""
|
||||
markers = "python_version == \"3.10\""
|
||||
files = [
|
||||
{file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"},
|
||||
{file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"},
|
||||
@@ -2824,6 +2848,21 @@ files = [
|
||||
{file = "iamdata-0.1.202507281.tar.gz", hash = "sha256:4050870068ca2fb044d03c46229bc8dbafb4f99db2f50c77297aafd437154ddd"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.12"
|
||||
description = "File identification library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "identify-2.6.12-py2.py3-none-any.whl", hash = "sha256:ad9672d5a72e0d2ff7c5c8809b62dfa60458626352fb0eb7b55e69bdc45334a2"},
|
||||
{file = "identify-2.6.12.tar.gz", hash = "sha256:d8de45749f1efb108badef65ee8386f0f7bb19a7f26185f74de6367bffbaf0e6"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
license = ["ukkonen"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
@@ -3899,7 +3938,7 @@ description = "Python package for creating and manipulating graphs and networks"
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
groups = ["dev"]
|
||||
markers = "python_version < \"3.11\""
|
||||
markers = "python_version == \"3.10\""
|
||||
files = [
|
||||
{file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"},
|
||||
{file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"},
|
||||
@@ -3961,6 +4000,18 @@ plot = ["matplotlib"]
|
||||
tgrep = ["pyparsing"]
|
||||
twitter = ["twython"]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.9.1"
|
||||
description = "Node.js virtual environment builder"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"},
|
||||
{file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.0.2"
|
||||
@@ -4392,32 +4443,24 @@ files = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prek"
|
||||
version = "0.3.8"
|
||||
description = "Better `pre-commit`, re-engineered in Rust"
|
||||
name = "pre-commit"
|
||||
version = "4.2.0"
|
||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "prek-0.3.8-py3-none-linux_armv6l.whl", hash = "sha256:6fb646ada60658fa6dd7771b2e0fb097f005151be222f869dada3eb26d79ed33"},
|
||||
{file = "prek-0.3.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f3d7fdadb15efc19c09953c7a33cf2061a70f367d1e1957358d3ad5cc49d0616"},
|
||||
{file = "prek-0.3.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:72728c3295e79ca443f8c1ec037d2a5b914ec73a358f69cf1bc1964511876bf8"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:48efc28f2f53b5b8087efca9daaed91572d62df97d5f24a1c7a087fecb5017de"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f6ca9d63bacbc448a5c18e955c78d3ac5176c3a17c3baacdd949b1a623e08a36"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1000f7029696b4fe712fb1fefd4c55b9c4de72b65509c8e50296370a06f9dc3f"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ff0bed0e2c1286522987d982168a86cbbd0d069d840506a46c9fda983515517"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fb087ac0ffda3ac65bbbae9a38326a7fd27ee007bb4a94323ce1eb539d8bbec"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:2e1e5e206ff7b31bd079cce525daddc96cd6bc544d20dc128921ad92f7a4c85d"},
|
||||
{file = "prek-0.3.8-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:dcea3fe23832a4481bccb7c45f55650cb233be7c805602e788bb7dba60f2d861"},
|
||||
{file = "prek-0.3.8-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:4d25e647e9682f6818ab5c31e7a4b842993c14782a6ffcd128d22b784e0d677f"},
|
||||
{file = "prek-0.3.8-py3-none-musllinux_1_1_i686.whl", hash = "sha256:de528b82935e33074815acff3c7c86026754d1212136295bc88fe9c43b4231d5"},
|
||||
{file = "prek-0.3.8-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:6d660f1c25a126e6d9f682fe61449441226514f412a4469f5d71f8f8cad56db2"},
|
||||
{file = "prek-0.3.8-py3-none-win32.whl", hash = "sha256:b0c291c577615d9f8450421dff0b32bfd77a6b0d223ee4115a1f820cb636fdf1"},
|
||||
{file = "prek-0.3.8-py3-none-win_amd64.whl", hash = "sha256:bc147fdbdd4ec33fc7a987b893ecb69b1413ac100d95c9889a70f3fd58c73d06"},
|
||||
{file = "prek-0.3.8-py3-none-win_arm64.whl", hash = "sha256:a2614647aeafa817a5802ccb9561e92eedc20dcf840639a1b00826e2c2442515"},
|
||||
{file = "prek-0.3.8.tar.gz", hash = "sha256:434a214256516f187a3ab15f869d950243be66b94ad47987ee4281b69643a2d9"},
|
||||
{file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"},
|
||||
{file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
cfgv = ">=2.0.0"
|
||||
identify = ">=1.0.0"
|
||||
nodeenv = ">=0.11.1"
|
||||
pyyaml = ">=5.1"
|
||||
virtualenv = ">=20.10.0"
|
||||
|
||||
[[package]]
|
||||
name = "propcache"
|
||||
version = "0.3.2"
|
||||
@@ -6051,7 +6094,7 @@ description = "A lil' TOML parser"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
markers = "python_version < \"3.11\""
|
||||
markers = "python_version == \"3.10\""
|
||||
files = [
|
||||
{file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
|
||||
{file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
|
||||
@@ -6238,6 +6281,27 @@ files = [
|
||||
{file = "uuid6-2024.7.10.tar.gz", hash = "sha256:2d29d7f63f593caaeea0e0d0dd0ad8129c9c663b29e19bdf882e864bedf18fb0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "20.32.0"
|
||||
description = "Virtual Python Environment builder"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "virtualenv-20.32.0-py3-none-any.whl", hash = "sha256:2c310aecb62e5aa1b06103ed7c2977b81e042695de2697d01017ff0f1034af56"},
|
||||
{file = "virtualenv-20.32.0.tar.gz", hash = "sha256:886bf75cadfdc964674e6e33eb74d787dff31ca314ceace03ca5810620f4ecf0"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
distlib = ">=0.3.7,<1"
|
||||
filelock = ">=3.12.2,<4"
|
||||
platformdirs = ">=3.9.1,<5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2,!=7.3)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8) ; platform_python_implementation == \"PyPy\" or platform_python_implementation == \"GraalVM\" or platform_python_implementation == \"CPython\" and sys_platform == \"win32\" and python_version >= \"3.13\"", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10) ; platform_python_implementation == \"CPython\""]
|
||||
|
||||
[[package]]
|
||||
name = "vulture"
|
||||
version = "2.14"
|
||||
@@ -6679,4 +6743,4 @@ files = [
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10,<3.13"
|
||||
content-hash = "eed563f8719cd06a8f11cc95123b6a3b2bfa4b4354a432da1e0728a334be0c05"
|
||||
content-hash = "91739ee5e383337160f9f08b76944ab4e8629c94084c8a9d115246862557f7c5"
|
||||
|
||||
@@ -33,6 +33,9 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- `--list-checks` and `--list-checks-json` now include `threat-detection` category checks in their output [(#10578)](https://github.com/prowler-cloud/prowler/pull/10578)
|
||||
- Missing `__init__.py` in `codebuild_project_uses_allowed_github_organizations` check preventing discovery by `--list-checks` [(#10584)](https://github.com/prowler-cloud/prowler/pull/10584)
|
||||
- Azure Key Vault checks emitting incorrect findings for keys, secrets, and vault logging [(#10332)](https://github.com/prowler-cloud/prowler/pull/10332)
|
||||
- `is_policy_public` now recognizes `kms:CallerAccount`, `kms:ViaService`, `aws:CalledVia`, `aws:CalledViaFirst`, and `aws:CalledViaLast` as restrictive condition keys, fixing false positives in `kms_key_policy_is_not_public` and other checks that use `is_condition_block_restrictive` [(#10600)](https://github.com/prowler-cloud/prowler/pull/10600)
|
||||
- `_enabled_regions` empty-set bug in `AwsProvider.generate_regional_clients` creating boto3 clients for all 36 AWS regions instead of the audited ones, causing random CI timeouts and slow test runs [(#10598)](https://github.com/prowler-cloud/prowler/pull/10598)
|
||||
- Retrieve only the latest version from a package in AWS CodeArtifact [(#10243)](https://github.com/prowler-cloud/prowler/pull/10243)
|
||||
|
||||
### 🔐 Security
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ class AwsProvider(Provider):
|
||||
_audit_resources: list = []
|
||||
_audit_config: dict
|
||||
_scan_unused_services: bool = False
|
||||
_enabled_regions: set = set()
|
||||
_enabled_regions: set | None = None
|
||||
_mutelist: AWSMutelist
|
||||
# TODO: this is not optional, enforce for all providers
|
||||
audit_metadata: Audit_Metadata
|
||||
@@ -747,7 +747,7 @@ class AwsProvider(Provider):
|
||||
)
|
||||
|
||||
# Get the regions enabled for the account and get the intersection with the service available regions
|
||||
if self._enabled_regions:
|
||||
if self._enabled_regions is not None:
|
||||
enabled_regions = service_regions.intersection(self._enabled_regions)
|
||||
else:
|
||||
enabled_regions = service_regions
|
||||
@@ -1104,14 +1104,14 @@ class AwsProvider(Provider):
|
||||
file=pathlib.Path(__file__).name,
|
||||
)
|
||||
|
||||
def get_aws_enabled_regions(self, current_session: Session) -> set:
|
||||
"""get_aws_enabled_regions returns a set of enabled AWS regions
|
||||
def get_aws_enabled_regions(self, current_session: Session) -> set | None:
|
||||
"""get_aws_enabled_regions returns a set of enabled AWS regions, or None on failure.
|
||||
|
||||
Args:
|
||||
- current_session: The AWS session object
|
||||
|
||||
Returns:
|
||||
- set: set of strings representing the enabled AWS regions
|
||||
- set | None: set of enabled AWS region strings, or None if regions could not be determined
|
||||
"""
|
||||
try:
|
||||
# EC2 Client to check enabled regions
|
||||
@@ -1131,7 +1131,7 @@ class AwsProvider(Provider):
|
||||
logger.error(
|
||||
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
|
||||
)
|
||||
return set()
|
||||
return None
|
||||
|
||||
# TODO: review this function
|
||||
# Maybe this should be done within the AwsProvider and not in __main__.py
|
||||
|
||||
@@ -96,6 +96,7 @@ class CodeArtifact(AWSService):
|
||||
namespace=package_namespace,
|
||||
package=package_name,
|
||||
sortBy="PUBLISHED_TIME",
|
||||
maxResults=1,
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -111,6 +112,7 @@ class CodeArtifact(AWSService):
|
||||
format=package_format,
|
||||
package=package_name,
|
||||
sortBy="PUBLISHED_TIME",
|
||||
maxResults=1,
|
||||
)
|
||||
)
|
||||
latest_version = ""
|
||||
|
||||
@@ -617,6 +617,11 @@ def is_condition_block_restrictive(
|
||||
"aws:sourceorgpaths",
|
||||
"aws:userid",
|
||||
"aws:username",
|
||||
"aws:calledvia",
|
||||
"aws:calledviafirst",
|
||||
"aws:calledvialast",
|
||||
"kms:calleraccount",
|
||||
"kms:viaservice",
|
||||
"s3:resourceaccount",
|
||||
"lambda:eventsourcetoken", # For Alexa Home functions, a token that the invoker must supply.
|
||||
],
|
||||
@@ -635,6 +640,11 @@ def is_condition_block_restrictive(
|
||||
"aws:sourceorgpaths",
|
||||
"aws:userid",
|
||||
"aws:username",
|
||||
"aws:calledvia",
|
||||
"aws:calledviafirst",
|
||||
"aws:calledvialast",
|
||||
"kms:calleraccount",
|
||||
"kms:viaservice",
|
||||
"s3:resourceaccount",
|
||||
"lambda:eventsourcetoken",
|
||||
],
|
||||
|
||||
@@ -95,8 +95,10 @@ class Route53(AWSService):
|
||||
region, so we need to query all enabled regions to avoid false positives.
|
||||
"""
|
||||
logger.info("Route53 - Gathering Elastic IPs from all regions...")
|
||||
all_regions = self.provider._enabled_regions or set(
|
||||
self.provider._identity.audited_regions
|
||||
all_regions = (
|
||||
self.provider._enabled_regions
|
||||
if self.provider._enabled_regions is not None
|
||||
else set(self.provider._identity.audited_regions)
|
||||
)
|
||||
|
||||
for region in all_regions:
|
||||
|
||||
@@ -127,7 +127,7 @@ mock = "5.2.0"
|
||||
moto = {extras = ["all"], version = "5.1.11"}
|
||||
openapi-schema-validator = "0.6.3"
|
||||
openapi-spec-validator = "0.7.1"
|
||||
prek = "0.3.8"
|
||||
pre-commit = "4.2.0"
|
||||
pylint = "3.3.4"
|
||||
pytest = "8.3.5"
|
||||
pytest-cov = "6.0.0"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Setup Git Hooks for Prowler
|
||||
# This script installs prek hooks using the project's Poetry environment
|
||||
# or a system-wide prek installation
|
||||
# This script installs pre-commit hooks using the project's Poetry environment
|
||||
|
||||
set -e
|
||||
|
||||
@@ -24,50 +23,43 @@ if ! git rev-parse --git-dir >/dev/null 2>&1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clear any existing core.hooksPath to avoid conflicts
|
||||
# Check if Poetry is installed
|
||||
if ! command -v poetry &>/dev/null; then
|
||||
echo -e "${RED}❌ Poetry is not installed${NC}"
|
||||
echo -e "${YELLOW} Install Poetry: https://python-poetry.org/docs/#installation${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if pyproject.toml exists
|
||||
if [ ! -f "pyproject.toml" ]; then
|
||||
echo -e "${RED}❌ pyproject.toml not found${NC}"
|
||||
echo -e "${YELLOW} Please run this script from the repository root${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if dependencies are already installed
|
||||
if ! poetry run python -c "import pre_commit" 2>/dev/null; then
|
||||
echo -e "${YELLOW}📦 Installing project dependencies (including pre-commit)...${NC}"
|
||||
poetry install --with dev
|
||||
else
|
||||
echo -e "${GREEN}✓${NC} Dependencies already installed"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
# Clear any existing core.hooksPath to avoid pre-commit conflicts
|
||||
if git config --get core.hooksPath >/dev/null 2>&1; then
|
||||
echo -e "${YELLOW}🧹 Clearing existing core.hooksPath configuration...${NC}"
|
||||
git config --unset-all core.hooksPath
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# Full setup requires Poetry for system hooks (pylint, bandit, safety, vulture, trufflehog)
|
||||
# These are installed as Python dev dependencies and used by local hooks in .pre-commit-config.yaml
|
||||
if command -v poetry &>/dev/null && [ -f "pyproject.toml" ]; then
|
||||
if poetry run prek --version &>/dev/null 2>&1; then
|
||||
echo -e "${GREEN}✓${NC} prek and dependencies found via Poetry"
|
||||
else
|
||||
echo -e "${YELLOW}📦 Installing project dependencies (including prek)...${NC}"
|
||||
poetry install --with dev
|
||||
fi
|
||||
echo -e "${YELLOW}🔗 Installing prek hooks...${NC}"
|
||||
poetry run prek install --overwrite
|
||||
elif command -v prek &>/dev/null; then
|
||||
# prek is available system-wide but without Poetry dev deps
|
||||
echo -e "${GREEN}✓${NC} prek found in PATH"
|
||||
echo -e "${YELLOW}🔗 Installing prek hooks...${NC}"
|
||||
prek install --overwrite
|
||||
echo ""
|
||||
echo -e "${YELLOW}⚠️ Warning: Some hooks require Python tools installed via Poetry:${NC}"
|
||||
echo -e " pylint, bandit, safety, vulture, trufflehog"
|
||||
echo -e " These hooks will be skipped unless you install them or run:"
|
||||
echo -e " ${GREEN}poetry install --with dev${NC}"
|
||||
else
|
||||
echo -e "${RED}❌ prek is not installed${NC}"
|
||||
echo -e "${YELLOW} Install prek using one of these methods:${NC}"
|
||||
echo -e " • brew install prek"
|
||||
echo -e " • pnpm add -g @j178/prek"
|
||||
echo -e " • pip install prek"
|
||||
echo -e " • See https://prek.j178.dev/installation/ for more options"
|
||||
exit 1
|
||||
fi
|
||||
echo -e "${YELLOW}🔗 Installing pre-commit hooks...${NC}"
|
||||
poetry run pre-commit install
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}✅ Git hooks successfully configured!${NC}"
|
||||
echo ""
|
||||
echo -e "${YELLOW}📋 Prek hook system:${NC}"
|
||||
echo -e " • Prek manages all git hooks"
|
||||
echo -e "${YELLOW}📋 Pre-commit system:${NC}"
|
||||
echo -e " • Python pre-commit manages all git hooks"
|
||||
echo -e " • API files: Python checks (black, flake8, bandit, etc.)"
|
||||
echo -e " • UI files: UI checks (TypeScript, ESLint, Claude Code validation)"
|
||||
echo ""
|
||||
|
||||
@@ -78,7 +78,9 @@ class TestAWSService:
|
||||
def test_AWSService_non_global_service_uses_profile_region(self):
|
||||
"""Non-global services should use the profile region when available."""
|
||||
service_name = "s3"
|
||||
provider = set_mocked_aws_provider(profile_region=AWS_REGION_EU_WEST_1)
|
||||
provider = set_mocked_aws_provider(
|
||||
audited_regions=[], profile_region=AWS_REGION_EU_WEST_1
|
||||
)
|
||||
service = AWSService(service_name, provider)
|
||||
|
||||
assert service.region == AWS_REGION_EU_WEST_1
|
||||
|
||||
@@ -312,7 +312,9 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
return_value=set_mocked_aws_provider(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1]
|
||||
),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client",
|
||||
@@ -552,7 +554,9 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
return_value=set_mocked_aws_provider(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1]
|
||||
),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client",
|
||||
@@ -615,7 +619,9 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
return_value=set_mocked_aws_provider(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1]
|
||||
),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client",
|
||||
@@ -690,7 +696,9 @@ class Test_awslambda_function_not_publicly_accessible:
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
return_value=set_mocked_aws_provider(
|
||||
audited_regions=[AWS_REGION_EU_WEST_1]
|
||||
),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.awslambda.awslambda_function_not_publicly_accessible.awslambda_function_not_publicly_accessible.awslambda_client",
|
||||
|
||||
@@ -54,6 +54,9 @@ def mock_make_api_call(self, operation_name, kwarg):
|
||||
}
|
||||
|
||||
if operation_name == "ListPackageVersions":
|
||||
assert (
|
||||
kwarg.get("maxResults") == 1
|
||||
), "list_package_versions must pass maxResults=1 to avoid fetching all versions"
|
||||
return {
|
||||
"defaultDisplayVersion": "latest",
|
||||
"format": "pypi",
|
||||
@@ -204,3 +207,102 @@ class Test_CodeArtifact_Service:
|
||||
.latest_version.origin.origin_type
|
||||
== OriginInformationValues.INTERNAL
|
||||
)
|
||||
|
||||
|
||||
def mock_make_api_call_no_namespace(self, operation_name, kwarg):
|
||||
"""Mock for packages without a namespace to exercise the else branch"""
|
||||
if operation_name == "ListRepositories":
|
||||
return {
|
||||
"repositories": [
|
||||
{
|
||||
"name": "test-repository",
|
||||
"administratorAccount": AWS_ACCOUNT_NUMBER,
|
||||
"domainName": "test-domain",
|
||||
"domainOwner": AWS_ACCOUNT_NUMBER,
|
||||
"arn": TEST_REPOSITORY_ARN,
|
||||
"description": "test description",
|
||||
},
|
||||
]
|
||||
}
|
||||
if operation_name == "ListPackages":
|
||||
return {
|
||||
"packages": [
|
||||
{
|
||||
"format": "pypi",
|
||||
"package": "test-package-no-ns",
|
||||
"originConfiguration": {
|
||||
"restrictions": {
|
||||
"publish": "ALLOW",
|
||||
"upstream": "BLOCK",
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
if operation_name == "ListPackageVersions":
|
||||
assert (
|
||||
kwarg.get("maxResults") == 1
|
||||
), "list_package_versions must pass maxResults=1 to avoid fetching all versions"
|
||||
assert (
|
||||
"namespace" not in kwarg
|
||||
), "namespace should not be passed when package has no namespace"
|
||||
return {
|
||||
"defaultDisplayVersion": "1.0.0",
|
||||
"format": "pypi",
|
||||
"package": "test-package-no-ns",
|
||||
"versions": [
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"revision": "abc123",
|
||||
"status": "Published",
|
||||
"origin": {
|
||||
"domainEntryPoint": {
|
||||
"repositoryName": "test-repository",
|
||||
"externalConnectionName": "",
|
||||
},
|
||||
"originType": "EXTERNAL",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
if operation_name == "ListTagsForResource":
|
||||
return {"tags": []}
|
||||
|
||||
return make_api_call(self, operation_name, kwarg)
|
||||
|
||||
|
||||
@patch(
|
||||
"botocore.client.BaseClient._make_api_call",
|
||||
new=mock_make_api_call_no_namespace,
|
||||
)
|
||||
@patch(
|
||||
"prowler.providers.aws.aws_provider.AwsProvider.generate_regional_clients",
|
||||
new=mock_generate_regional_clients,
|
||||
)
|
||||
class Test_CodeArtifact_Service_No_Namespace:
|
||||
def test_list_packages_no_namespace(self):
|
||||
codeartifact = CodeArtifact(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1])
|
||||
)
|
||||
|
||||
assert len(codeartifact.repositories[TEST_REPOSITORY_ARN].packages) == 1
|
||||
|
||||
package = codeartifact.repositories[TEST_REPOSITORY_ARN].packages[0]
|
||||
assert package.name == "test-package-no-ns"
|
||||
assert package.namespace is None
|
||||
assert package.format == "pypi"
|
||||
assert (
|
||||
package.origin_configuration.restrictions.publish == RestrictionValues.ALLOW
|
||||
)
|
||||
assert (
|
||||
package.origin_configuration.restrictions.upstream
|
||||
== RestrictionValues.BLOCK
|
||||
)
|
||||
assert package.latest_version.version == "1.0.0"
|
||||
assert package.latest_version.status == LatestPackageVersionStatus.Published
|
||||
assert (
|
||||
package.latest_version.origin.origin_type
|
||||
== OriginInformationValues.EXTERNAL
|
||||
)
|
||||
|
||||
@@ -139,7 +139,7 @@ class Test_Codebuild_Service:
|
||||
)
|
||||
@mock_aws
|
||||
def test_codebuild_service(self):
|
||||
codebuild = Codebuild(set_mocked_aws_provider())
|
||||
codebuild = Codebuild(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
|
||||
assert codebuild.session.__class__.__name__ == "Session"
|
||||
assert codebuild.service == "codebuild"
|
||||
|
||||
@@ -76,7 +76,7 @@ class Test_CodePipeline_Service:
|
||||
)
|
||||
@mock_aws
|
||||
def test_codepipeline_service(self):
|
||||
codepipeline = CodePipeline(set_mocked_aws_provider())
|
||||
codepipeline = CodePipeline(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
|
||||
assert codepipeline.session.__class__.__name__ == "Session"
|
||||
assert codepipeline.service == "codepipeline"
|
||||
|
||||
@@ -106,27 +106,27 @@ def mock_generate_regional_clients(provider, service):
|
||||
class Test_DataSync_Service:
|
||||
# Test DataSync Service initialization
|
||||
def test_service(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
datasync = DataSync(aws_provider)
|
||||
assert datasync.service == "datasync"
|
||||
|
||||
# Test DataSync clients creation
|
||||
def test_client(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
datasync = DataSync(aws_provider)
|
||||
for reg_client in datasync.regional_clients.values():
|
||||
assert reg_client.__class__.__name__ == "DataSync"
|
||||
|
||||
# Test DataSync session
|
||||
def test__get_session__(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
datasync = DataSync(aws_provider)
|
||||
assert datasync.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test listing DataSync tasks
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
def test_list_tasks(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
datasync = DataSync(aws_provider)
|
||||
|
||||
task_arn = "arn:aws:datasync:eu-west-1:123456789012:task/task-12345678901234567"
|
||||
@@ -142,7 +142,7 @@ class Test_DataSync_Service:
|
||||
|
||||
# Test generic exception in list_tasks
|
||||
def test_list_tasks_generic_exception(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
# Mock the regional client's list_tasks method specifically
|
||||
mock_client = MagicMock()
|
||||
@@ -155,7 +155,7 @@ class Test_DataSync_Service:
|
||||
# Test describing DataSync tasks with various exceptions
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
def test_describe_tasks_with_exceptions(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
datasync = DataSync(aws_provider)
|
||||
|
||||
# Check all tasks were processed despite exceptions
|
||||
@@ -183,7 +183,7 @@ class Test_DataSync_Service:
|
||||
# Test listing task tags with various exceptions
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
def test_list_task_tags_with_exceptions(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
datasync = DataSync(aws_provider)
|
||||
|
||||
tasks_by_name = {task.name: task for task in datasync.tasks.values()}
|
||||
|
||||
@@ -170,20 +170,20 @@ def mock_generate_regional_clients(provider, service):
|
||||
class Test_ECR_Service:
|
||||
# Test ECR Service
|
||||
def test_service(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
assert ecr.service == "ecr"
|
||||
|
||||
# Test ECR client
|
||||
def test_client(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
for regional_client in ecr.regional_clients.values():
|
||||
assert regional_client.__class__.__name__ == "ECR"
|
||||
|
||||
# Test ECR session
|
||||
def test_get_session(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
assert ecr.session.__class__.__name__ == "Session"
|
||||
|
||||
@@ -198,7 +198,7 @@ class Test_ECR_Service:
|
||||
{"Key": "test", "Value": "test"},
|
||||
],
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
|
||||
assert len(ecr.registries) == 1
|
||||
@@ -226,7 +226,7 @@ class Test_ECR_Service:
|
||||
imageScanningConfiguration={"scanOnPush": True},
|
||||
imageTagMutability="IMMUTABLE",
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
assert len(ecr.registries) == 1
|
||||
assert len(ecr.registries[AWS_REGION_EU_WEST_1].repositories) == 1
|
||||
@@ -255,7 +255,7 @@ class Test_ECR_Service:
|
||||
imageScanningConfiguration={"scanOnPush": True},
|
||||
imageTagMutability="IMMUTABLE",
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
assert len(ecr.registries) == 1
|
||||
assert len(ecr.registries[AWS_REGION_EU_WEST_1].repositories) == 1
|
||||
@@ -273,7 +273,7 @@ class Test_ECR_Service:
|
||||
repositoryName=repo_name,
|
||||
imageScanningConfiguration={"scanOnPush": True},
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
|
||||
assert len(ecr.registries) == 1
|
||||
@@ -366,7 +366,7 @@ class Test_ECR_Service:
|
||||
# Test get ECR Registries Scanning Configuration
|
||||
@mock_aws
|
||||
def test_get_registry_scanning_configuration(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecr = ECR(aws_provider)
|
||||
assert len(ecr.registries) == 1
|
||||
assert ecr.registries[AWS_REGION_EU_WEST_1].id == AWS_ACCOUNT_NUMBER
|
||||
|
||||
@@ -122,27 +122,27 @@ def mock_generate_regional_clients(provider, service):
|
||||
class Test_ECS_Service:
|
||||
# Test ECS Service
|
||||
def test_service(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
assert ecs.service == "ecs"
|
||||
|
||||
# Test ECS client
|
||||
def test_client(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
for reg_client in ecs.regional_clients.values():
|
||||
assert reg_client.__class__.__name__ == "ECS"
|
||||
|
||||
# Test ECS session
|
||||
def test__get_session__(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
assert ecs.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test list ECS task definitions
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
def test_list_task_definitions(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
|
||||
task_arn = "arn:aws:ecs:eu-west-1:123456789012:task-definition/test_cluster_1/test_ecs_task:1"
|
||||
@@ -156,7 +156,7 @@ class Test_ECS_Service:
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test describe ECS task definitions
|
||||
def test_describe_task_definitions(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
|
||||
task_arn = "arn:aws:ecs:eu-west-1:123456789012:task-definition/test_cluster_1/test_ecs_task:1"
|
||||
@@ -204,7 +204,7 @@ class Test_ECS_Service:
|
||||
# Test list ECS clusters
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
def test_list_clusters(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
|
||||
cluster_arn1 = "arn:aws:ecs:eu-west-1:123456789012:cluster/test_cluster_1"
|
||||
@@ -217,7 +217,7 @@ class Test_ECS_Service:
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test describe ECS clusters
|
||||
def test_describe_clusters(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
|
||||
cluster_arn1 = "arn:aws:ecs:eu-west-1:123456789012:cluster/test_cluster_1"
|
||||
@@ -237,7 +237,7 @@ class Test_ECS_Service:
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test describe ECS services
|
||||
def test_describe_services(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
ecs = ECS(aws_provider)
|
||||
|
||||
service_arn = (
|
||||
|
||||
@@ -93,18 +93,18 @@ def mock_generate_regional_clients(provider, service):
|
||||
class Test_EFS:
|
||||
# Test EFS Session
|
||||
def test__get_session__(self):
|
||||
access_analyzer = EFS(set_mocked_aws_provider())
|
||||
access_analyzer = EFS(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
assert access_analyzer.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test EFS Service
|
||||
def test__get_service__(self):
|
||||
access_analyzer = EFS(set_mocked_aws_provider())
|
||||
access_analyzer = EFS(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
assert access_analyzer.service == "efs"
|
||||
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test EFS describe file systems
|
||||
def test_describe_file_systems(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
efs = EFS(aws_provider)
|
||||
efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:file-system/{FILE_SYSTEM_ID}"
|
||||
assert len(efs.filesystems) == 1
|
||||
@@ -119,7 +119,7 @@ class Test_EFS:
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test EFS describe file systems policies
|
||||
def test_describe_file_system_policies(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
efs = EFS(aws_provider)
|
||||
efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:file-system/{FILE_SYSTEM_ID}"
|
||||
assert len(efs.filesystems) == 1
|
||||
@@ -131,7 +131,7 @@ class Test_EFS:
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test EFS describe mount targets
|
||||
def test_describe_mount_targets(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
efs = EFS(aws_provider)
|
||||
assert len(efs.filesystems) == 1
|
||||
efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:file-system/{FILE_SYSTEM_ID}"
|
||||
@@ -144,7 +144,7 @@ class Test_EFS:
|
||||
@patch("botocore.client.BaseClient._make_api_call", new=mock_make_api_call)
|
||||
# Test EFS describe access points
|
||||
def test_describe_access_points(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
efs = EFS(aws_provider)
|
||||
assert len(efs.filesystems) == 1
|
||||
efs_arn = f"arn:aws:elasticfilesystem:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:file-system/{FILE_SYSTEM_ID}"
|
||||
|
||||
@@ -31,20 +31,20 @@ def mock_generate_regional_clients(provider, service):
|
||||
class Test_EKS_Service:
|
||||
# Test EKS Service
|
||||
def test_service(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
eks = EKS(aws_provider)
|
||||
assert eks.service == "eks"
|
||||
|
||||
# Test EKS client
|
||||
def test_client(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
eks = EKS(aws_provider)
|
||||
for reg_client in eks.regional_clients.values():
|
||||
assert reg_client.__class__.__name__ == "EKS"
|
||||
|
||||
# Test EKS session
|
||||
def test__get_session__(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
eks = EKS(aws_provider)
|
||||
assert eks.session.__class__.__name__ == "Session"
|
||||
|
||||
@@ -73,7 +73,7 @@ class Test_EKS_Service:
|
||||
roleArn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/eks-service-role-AWSServiceRoleForAmazonEKS-J7ONKE3BQ4PI",
|
||||
tags={"test": "test"},
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
eks = EKS(aws_provider)
|
||||
assert len(eks.clusters) == 1
|
||||
assert eks.clusters[0].name == cluster_name
|
||||
@@ -126,7 +126,7 @@ class Test_EKS_Service:
|
||||
},
|
||||
],
|
||||
)
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
eks = EKS(aws_provider)
|
||||
assert len(eks.clusters) == 1
|
||||
assert eks.clusters[0].name == cluster_name
|
||||
|
||||
@@ -59,7 +59,9 @@ class Test_ElasticBeanstalk_Service:
|
||||
# Test ElasticBeanstalk Client
|
||||
@mock_aws
|
||||
def test_get_client(self):
|
||||
elasticbeanstalk = ElasticBeanstalk(set_mocked_aws_provider())
|
||||
elasticbeanstalk = ElasticBeanstalk(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
)
|
||||
assert (
|
||||
elasticbeanstalk.regional_clients[AWS_REGION_EU_WEST_1].__class__.__name__
|
||||
== "ElasticBeanstalk"
|
||||
@@ -68,13 +70,17 @@ class Test_ElasticBeanstalk_Service:
|
||||
# Test ElasticBeanstalk Session
|
||||
@mock_aws
|
||||
def test__get_session__(self):
|
||||
elasticbeanstalk = ElasticBeanstalk(set_mocked_aws_provider())
|
||||
elasticbeanstalk = ElasticBeanstalk(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
)
|
||||
assert elasticbeanstalk.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test ElasticBeanstalk Service
|
||||
@mock_aws
|
||||
def test__get_service__(self):
|
||||
elasticbeanstalk = ElasticBeanstalk(set_mocked_aws_provider())
|
||||
elasticbeanstalk = ElasticBeanstalk(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
)
|
||||
assert elasticbeanstalk.service == "elasticbeanstalk"
|
||||
|
||||
# Test _describe_environments
|
||||
@@ -90,7 +96,9 @@ class Test_ElasticBeanstalk_Service:
|
||||
EnvironmentName="test-env",
|
||||
)
|
||||
# ElasticBeanstalk Class
|
||||
elasticbeanstalk = ElasticBeanstalk(set_mocked_aws_provider())
|
||||
elasticbeanstalk = ElasticBeanstalk(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
)
|
||||
|
||||
assert len(elasticbeanstalk.environments) == 1
|
||||
assert (
|
||||
@@ -125,7 +133,9 @@ class Test_ElasticBeanstalk_Service:
|
||||
EnvironmentName="test-env",
|
||||
)
|
||||
# ElasticBeanstalk Class
|
||||
elasticbeanstalk = ElasticBeanstalk(set_mocked_aws_provider())
|
||||
elasticbeanstalk = ElasticBeanstalk(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
)
|
||||
assert (
|
||||
elasticbeanstalk.environments[
|
||||
environment["EnvironmentArn"]
|
||||
@@ -158,7 +168,9 @@ class Test_ElasticBeanstalk_Service:
|
||||
Tags=[{"Key": "test-key", "Value": "test-value"}],
|
||||
)
|
||||
# ElasticBeanstalk Class
|
||||
elasticbeanstalk = ElasticBeanstalk(set_mocked_aws_provider())
|
||||
elasticbeanstalk = ElasticBeanstalk(
|
||||
set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
)
|
||||
assert elasticbeanstalk.environments[environment["EnvironmentArn"]].tags == [
|
||||
{"Key": "test-key", "Value": "test-value"}
|
||||
]
|
||||
|
||||
@@ -91,7 +91,11 @@ class Test_emr_cluster_publicly_accesible:
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.emr.emr_cluster_publicly_accesible.emr_cluster_publicly_accesible.ec2_client",
|
||||
new=EC2(set_mocked_aws_provider(create_default_organization=False)),
|
||||
new=EC2(
|
||||
set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1], create_default_organization=False
|
||||
)
|
||||
),
|
||||
),
|
||||
):
|
||||
# Test Check
|
||||
@@ -161,7 +165,11 @@ class Test_emr_cluster_publicly_accesible:
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.emr.emr_cluster_publicly_accesible.emr_cluster_publicly_accesible.ec2_client",
|
||||
new=EC2(set_mocked_aws_provider(create_default_organization=False)),
|
||||
new=EC2(
|
||||
set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1], create_default_organization=False
|
||||
)
|
||||
),
|
||||
),
|
||||
):
|
||||
# Test Check
|
||||
@@ -248,7 +256,11 @@ class Test_emr_cluster_publicly_accesible:
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.emr.emr_cluster_publicly_accesible.emr_cluster_publicly_accesible.ec2_client",
|
||||
new=EC2(set_mocked_aws_provider(create_default_organization=False)),
|
||||
new=EC2(
|
||||
set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1], create_default_organization=False
|
||||
)
|
||||
),
|
||||
),
|
||||
):
|
||||
# Test Check
|
||||
@@ -338,7 +350,11 @@ class Test_emr_cluster_publicly_accesible:
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.emr.emr_cluster_publicly_accesible.emr_cluster_publicly_accesible.ec2_client",
|
||||
new=EC2(set_mocked_aws_provider(create_default_organization=False)),
|
||||
new=EC2(
|
||||
set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1], create_default_organization=False
|
||||
)
|
||||
),
|
||||
),
|
||||
):
|
||||
# Test Check
|
||||
@@ -425,7 +441,11 @@ class Test_emr_cluster_publicly_accesible:
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.emr.emr_cluster_publicly_accesible.emr_cluster_publicly_accesible.ec2_client",
|
||||
new=EC2(set_mocked_aws_provider(create_default_organization=False)),
|
||||
new=EC2(
|
||||
set_mocked_aws_provider(
|
||||
[AWS_REGION_EU_WEST_1], create_default_organization=False
|
||||
)
|
||||
),
|
||||
),
|
||||
):
|
||||
# Test Check
|
||||
|
||||
@@ -53,19 +53,19 @@ class Test_EMR_Service:
|
||||
# Test EMR Client
|
||||
@mock_aws
|
||||
def test_get_client(self):
|
||||
emr = EMR(set_mocked_aws_provider())
|
||||
emr = EMR(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
assert emr.regional_clients[AWS_REGION_EU_WEST_1].__class__.__name__ == "EMR"
|
||||
|
||||
# Test EMR Session
|
||||
@mock_aws
|
||||
def test__get_session__(self):
|
||||
emr = EMR(set_mocked_aws_provider())
|
||||
emr = EMR(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
assert emr.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test EMR Service
|
||||
@mock_aws
|
||||
def test__get_service__(self):
|
||||
emr = EMR(set_mocked_aws_provider())
|
||||
emr = EMR(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
assert emr.service == "emr"
|
||||
|
||||
# Test _list_clusters and _describe_cluster
|
||||
@@ -93,7 +93,7 @@ class Test_EMR_Service:
|
||||
)
|
||||
cluster_id = emr_client.run_job_flow(**run_job_flow_args)["JobFlowId"]
|
||||
# EMR Class
|
||||
emr = EMR(set_mocked_aws_provider())
|
||||
emr = EMR(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
|
||||
assert len(emr.clusters) == 1
|
||||
assert emr.clusters[cluster_id].id == cluster_id
|
||||
@@ -115,7 +115,7 @@ class Test_EMR_Service:
|
||||
|
||||
@mock_aws
|
||||
def test_get_block_public_access_configuration(self):
|
||||
emr = EMR(set_mocked_aws_provider())
|
||||
emr = EMR(set_mocked_aws_provider([AWS_REGION_EU_WEST_1]))
|
||||
|
||||
assert len(emr.block_public_access_configuration) == 1
|
||||
assert emr.block_public_access_configuration[
|
||||
|
||||
@@ -55,27 +55,27 @@ class Test_GlobalAccelerator_Service:
|
||||
# Test GlobalAccelerator Service
|
||||
def test_service(self):
|
||||
# GlobalAccelerator client for this test class
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_WEST_2])
|
||||
globalaccelerator = GlobalAccelerator(aws_provider)
|
||||
assert globalaccelerator.service == "globalaccelerator"
|
||||
|
||||
# Test GlobalAccelerator Client
|
||||
def test_client(self):
|
||||
# GlobalAccelerator client for this test class
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_WEST_2])
|
||||
globalaccelerator = GlobalAccelerator(aws_provider)
|
||||
assert globalaccelerator.client.__class__.__name__ == "GlobalAccelerator"
|
||||
|
||||
# Test GlobalAccelerator Session
|
||||
def test__get_session__(self):
|
||||
# GlobalAccelerator client for this test class
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_WEST_2])
|
||||
globalaccelerator = GlobalAccelerator(aws_provider)
|
||||
assert globalaccelerator.session.__class__.__name__ == "Session"
|
||||
|
||||
def test_list_accelerators(self):
|
||||
# GlobalAccelerator client for this test class
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_WEST_2])
|
||||
globalaccelerator = GlobalAccelerator(aws_provider)
|
||||
|
||||
accelerator_name = "TestAccelerator"
|
||||
@@ -99,7 +99,7 @@ class Test_GlobalAccelerator_Service:
|
||||
|
||||
def test_list_tags(self):
|
||||
# GlobalAccelerator client for this test class
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_WEST_2])
|
||||
globalaccelerator = GlobalAccelerator(aws_provider)
|
||||
|
||||
assert len(globalaccelerator.accelerators) == 1
|
||||
|
||||
@@ -39,7 +39,7 @@ def mock_make_api_call_members_managers(self, operation_name, api_params):
|
||||
class Test_guardduty_centrally_managed:
|
||||
@mock_aws
|
||||
def test_no_detectors(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -67,7 +67,7 @@ class Test_guardduty_centrally_managed:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -112,7 +112,7 @@ class Test_guardduty_centrally_managed:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -156,7 +156,7 @@ class Test_guardduty_centrally_managed:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class Test_guardduty_delegated_admin_enabled_all_regions:
|
||||
@mock_aws
|
||||
def test_no_detectors(self):
|
||||
"""Test when no GuardDuty detectors exist."""
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -102,7 +102,7 @@ class Test_guardduty_delegated_admin_enabled_all_regions:
|
||||
guardduty_client_boto = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
detector_id = guardduty_client_boto.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -148,7 +148,7 @@ class Test_guardduty_delegated_admin_enabled_all_regions:
|
||||
guardduty_client_boto = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
detector_id = guardduty_client_boto.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -194,7 +194,7 @@ class Test_guardduty_delegated_admin_enabled_all_regions:
|
||||
guardduty_client_boto = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
detector_id = guardduty_client_boto.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ def mock_make_api_call(self, operation_name, kwarg):
|
||||
|
||||
class Test_guardduty_ec2_malware_protection_enabled:
|
||||
def test_no_detectors(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -74,7 +74,7 @@ class Test_guardduty_ec2_malware_protection_enabled:
|
||||
|
||||
guardduty_client.create_detector(Enable=False)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -112,7 +112,7 @@ class Test_guardduty_ec2_malware_protection_enabled:
|
||||
},
|
||||
)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -161,7 +161,7 @@ class Test_guardduty_ec2_malware_protection_enabled:
|
||||
},
|
||||
)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from tests.providers.aws.utils import (
|
||||
|
||||
class Test_guardduty_eks_audit_log_enabled:
|
||||
def test_no_detectors(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -42,7 +42,7 @@ class Test_guardduty_eks_audit_log_enabled:
|
||||
|
||||
guardduty_client.create_detector(Enable=False)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -74,7 +74,7 @@ class Test_guardduty_eks_audit_log_enabled:
|
||||
Enable=True, DataSources={"Kubernetes": {"AuditLogs": {"Enable": True}}}
|
||||
)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -118,7 +118,7 @@ class Test_guardduty_eks_audit_log_enabled:
|
||||
Enable=True, DataSources={"Kubernetes": {"AuditLogs": {"Enable": False}}}
|
||||
)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ from moto import mock_aws
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_EU_WEST_1,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
@@ -13,7 +14,7 @@ from tests.providers.aws.utils import (
|
||||
class Test_guardduty_is_enabled:
|
||||
@mock_aws
|
||||
def test_no_detectors(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -43,7 +44,7 @@ class Test_guardduty_is_enabled:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -85,7 +86,7 @@ class Test_guardduty_is_enabled:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=False)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -131,7 +132,7 @@ class Test_guardduty_is_enabled:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=False)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -177,7 +178,9 @@ class Test_guardduty_is_enabled:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=False)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider(
|
||||
[AWS_REGION_US_EAST_1, AWS_REGION_EU_WEST_1]
|
||||
)
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ orig = botocore.client.BaseClient._make_api_call
|
||||
|
||||
class Test_guardduty_lambda_protection_enabled:
|
||||
def test_no_detectors(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -45,7 +45,7 @@ class Test_guardduty_lambda_protection_enabled:
|
||||
|
||||
guardduty_client.create_detector(Enable=False)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -78,7 +78,7 @@ class Test_guardduty_lambda_protection_enabled:
|
||||
Features=[{"Name": "LAMBDA_NETWORK_LOGS", "Status": "ENABLED"}],
|
||||
)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -123,7 +123,7 @@ class Test_guardduty_lambda_protection_enabled:
|
||||
Features=[{"Name": "LAMBDA_NETWORK_LOGS", "Status": "DISABLED"}],
|
||||
)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ def mock_make_api_call(self, operation_name, kwarg):
|
||||
class Test_guardduty_no_high_severity_findings:
|
||||
@mock_aws
|
||||
def test_no_detectors(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -56,7 +56,7 @@ class Test_guardduty_no_high_severity_findings:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
@@ -97,7 +97,7 @@ class Test_guardduty_no_high_severity_findings:
|
||||
|
||||
detector_id = guardduty_client.create_detector(Enable=True)["DetectorId"]
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
|
||||
from prowler.providers.aws.services.guardduty.guardduty_service import GuardDuty
|
||||
|
||||
|
||||
@@ -66,20 +66,20 @@ def mock_generate_regional_clients(provider, service):
|
||||
class Test_GuardDuty_Service:
|
||||
# Test GuardDuty Service
|
||||
def test_service(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
assert guardduty.service == "guardduty"
|
||||
|
||||
# Test GuardDuty client
|
||||
def test_client(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
for reg_client in guardduty.regional_clients.values():
|
||||
assert reg_client.__class__.__name__ == "GuardDuty"
|
||||
|
||||
# Test GuardDuty session
|
||||
def test__get_session__(self):
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
assert guardduty.session.__class__.__name__ == "Session"
|
||||
|
||||
@@ -89,7 +89,7 @@ class Test_GuardDuty_Service:
|
||||
guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
response = guardduty_client.create_detector(Enable=True, Tags={"test": "test"})
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
|
||||
assert len(guardduty.detectors) == 1
|
||||
@@ -121,7 +121,7 @@ class Test_GuardDuty_Service:
|
||||
],
|
||||
)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
|
||||
assert len(guardduty.detectors) == 1
|
||||
@@ -149,7 +149,7 @@ class Test_GuardDuty_Service:
|
||||
guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
response = guardduty_client.create_detector(Enable=True)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
|
||||
assert len(guardduty.detectors) == 1
|
||||
@@ -170,7 +170,7 @@ class Test_GuardDuty_Service:
|
||||
guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
response = guardduty_client.create_detector(Enable=True)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
|
||||
assert len(guardduty.detectors) == 1
|
||||
@@ -192,7 +192,7 @@ class Test_GuardDuty_Service:
|
||||
guardduty_client = client("guardduty", region_name=AWS_REGION_EU_WEST_1)
|
||||
response = guardduty_client.create_detector(Enable=True)
|
||||
|
||||
aws_provider = set_mocked_aws_provider()
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
guardduty = GuardDuty(aws_provider)
|
||||
|
||||
assert len(guardduty.detectors) == 1
|
||||
|
||||
@@ -1413,6 +1413,115 @@ class Test_Policy:
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_aws_CalledVia_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"aws:CalledVia": "cloudformation.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_aws_CalledViaFirst_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"aws:CalledViaFirst": "cloudformation.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_aws_CalledViaLast_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"aws:CalledViaLast": "glue.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_aws_CalledVia_str(self):
|
||||
condition_statement = {"StringLike": {"aws:CalledVia": "*.amazonaws.com"}}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_str_not_valid(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:CallerAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert not is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_list(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:CallerAccount": [TRUSTED_AWS_ACCOUNT_NUMBER]}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_CallerAccount_list_not_valid(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {
|
||||
"kms:CallerAccount": [
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
NON_TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
]
|
||||
}
|
||||
}
|
||||
assert not is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_equals_kms_ViaService_str(self):
|
||||
condition_statement = {
|
||||
"StringEquals": {"kms:ViaService": "glue.eu-central-1.amazonaws.com"}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_kms_CallerAccount_str(self):
|
||||
condition_statement = {
|
||||
"StringLike": {"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_kms_CallerAccount_str_not_valid(self):
|
||||
condition_statement = {
|
||||
"StringLike": {"kms:CallerAccount": NON_TRUSTED_AWS_ACCOUNT_NUMBER}
|
||||
}
|
||||
assert not is_condition_block_restrictive(
|
||||
condition_statement, TRUSTED_AWS_ACCOUNT_NUMBER
|
||||
)
|
||||
|
||||
def test_condition_parser_string_like_kms_ViaService_str(self):
|
||||
condition_statement = {"StringLike": {"kms:ViaService": "glue.*.amazonaws.com"}}
|
||||
assert is_condition_block_restrictive(
|
||||
condition_statement,
|
||||
TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
is_cross_account_allowed=True,
|
||||
)
|
||||
|
||||
def test_condition_parser_two_lists_unrestrictive(self):
|
||||
condition_statement = {
|
||||
"StringLike": {
|
||||
@@ -2357,6 +2466,71 @@ class Test_Policy:
|
||||
trusted_ips=["1.2.3.4", "5.6.7.8"],
|
||||
)
|
||||
|
||||
def test_is_policy_public_kms_caller_account_and_via_service(self):
|
||||
policy = {
|
||||
"Version": "2008-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": [
|
||||
"kms:Encrypt",
|
||||
"kms:Decrypt",
|
||||
"kms:ReEncrypt*",
|
||||
"kms:GenerateDataKey*",
|
||||
"kms:CreateGrant",
|
||||
"kms:DescribeKey",
|
||||
],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"kms:ViaService": "glue.eu-central-1.amazonaws.com",
|
||||
"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
||||
|
||||
def test_is_policy_public_kms_caller_account_only(self):
|
||||
policy = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": ["kms:Decrypt"],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"kms:CallerAccount": TRUSTED_AWS_ACCOUNT_NUMBER,
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
||||
|
||||
def test_is_policy_public_kms_via_service_without_account_restriction(self):
|
||||
policy = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Principal": {"AWS": "*"},
|
||||
"Action": ["kms:Decrypt"],
|
||||
"Resource": "*",
|
||||
"Condition": {
|
||||
"StringEquals": {
|
||||
"kms:ViaService": "glue.eu-central-1.amazonaws.com",
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
assert not is_policy_public(policy, TRUSTED_AWS_ACCOUNT_NUMBER)
|
||||
|
||||
def test_check_admin_access(self):
|
||||
policy = {
|
||||
"Version": "2012-10-17",
|
||||
|
||||
@@ -104,26 +104,26 @@ def mock_generate_regional_clients(provider, service):
|
||||
class TestOpenSearchServiceService:
|
||||
# Test OpenSearchService Service
|
||||
def test_service(self):
|
||||
aws_provider = set_mocked_aws_provider([])
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
opensearch = OpenSearchService(aws_provider)
|
||||
assert opensearch.service == "opensearch"
|
||||
|
||||
# Test OpenSearchService_ client
|
||||
def test_client(self):
|
||||
aws_provider = set_mocked_aws_provider([])
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
opensearch = OpenSearchService(aws_provider)
|
||||
for reg_client in opensearch.regional_clients.values():
|
||||
assert reg_client.__class__.__name__ == "OpenSearchService"
|
||||
|
||||
# Test OpenSearchService session
|
||||
def test__get_session__(self):
|
||||
aws_provider = set_mocked_aws_provider([])
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
opensearch = OpenSearchService(aws_provider)
|
||||
assert opensearch.session.__class__.__name__ == "Session"
|
||||
|
||||
# Test OpenSearchService list domains names
|
||||
def test_list_domain_names(self):
|
||||
aws_provider = set_mocked_aws_provider([])
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
opensearch = OpenSearchService(aws_provider)
|
||||
assert len(opensearch.opensearch_domains) == 1
|
||||
assert opensearch.opensearch_domains[domain_arn].name == test_domain_name
|
||||
@@ -132,7 +132,7 @@ class TestOpenSearchServiceService:
|
||||
# Test OpenSearchService describe domain
|
||||
@mock_aws
|
||||
def test_describe_domain(self):
|
||||
aws_provider = set_mocked_aws_provider([])
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
opensearch = OpenSearchService(aws_provider)
|
||||
assert len(opensearch.opensearch_domains) == 1
|
||||
assert opensearch.opensearch_domains[domain_arn].name == test_domain_name
|
||||
@@ -237,7 +237,7 @@ class TestOpenSearchServiceService:
|
||||
"botocore.client.BaseClient._make_api_call",
|
||||
new=mock_make_api_call_missing_fields,
|
||||
):
|
||||
aws_provider = set_mocked_aws_provider([])
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
|
||||
opensearch = OpenSearchService(aws_provider)
|
||||
|
||||
# Should not crash even with missing optional fields
|
||||
|
||||
@@ -248,6 +248,7 @@ class Test_rds_instance_no_public_access:
|
||||
PubliclyAccessible=True,
|
||||
VpcSecurityGroupIds=[default_sg_id],
|
||||
)
|
||||
from prowler.providers.aws.services.ec2.ec2_service import EC2
|
||||
from prowler.providers.aws.services.rds.rds_service import RDS
|
||||
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
@@ -256,9 +257,15 @@ class Test_rds_instance_no_public_access:
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
):
|
||||
with mock.patch(
|
||||
"prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access.rds_client",
|
||||
new=RDS(aws_provider),
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access.rds_client",
|
||||
new=RDS(aws_provider),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access.ec2_client",
|
||||
new=EC2(aws_provider),
|
||||
),
|
||||
):
|
||||
# Test Check
|
||||
from prowler.providers.aws.services.rds.rds_instance_no_public_access.rds_instance_no_public_access import (
|
||||
|
||||
@@ -96,7 +96,7 @@ ADMINISTRATOR_ROLE_ASSUME_ROLE_POLICY = {
|
||||
# This here causes to call this function mocking the AWS calls
|
||||
@mock_aws
|
||||
def set_mocked_aws_provider(
|
||||
audited_regions: list[str] = [],
|
||||
audited_regions: list[str] = [AWS_REGION_US_EAST_1],
|
||||
audited_account: str = AWS_ACCOUNT_NUMBER,
|
||||
audited_account_arn: str = AWS_ACCOUNT_ARN,
|
||||
audited_partition: str = AWS_COMMERCIAL_PARTITION,
|
||||
@@ -143,7 +143,9 @@ def set_mocked_aws_provider(
|
||||
# Mock Configiration
|
||||
provider._scan_unused_services = scan_unused_services
|
||||
provider._enabled_regions = (
|
||||
enabled_regions if enabled_regions else set(audited_regions)
|
||||
enabled_regions
|
||||
if enabled_regions is not None
|
||||
else (set(audited_regions) if audited_regions else None)
|
||||
)
|
||||
# TODO: we can create the organizations metadata here with moto
|
||||
provider._organizations_metadata = None
|
||||
|
||||
10
ui/README.md
10
ui/README.md
@@ -142,12 +142,12 @@ Or remove the variable from your `.env` file.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
If hooks aren't running after commits, verify prek is installed and hooks are set up:
|
||||
If hooks aren't running after commits:
|
||||
|
||||
```bash
|
||||
# Check prek is available
|
||||
prek --version
|
||||
# Verify hooks are configured
|
||||
git config --get core.hooksPath # Should output: ui/.husky
|
||||
|
||||
# Re-install hooks if needed
|
||||
prek install --overwrite
|
||||
# Reconfigure if needed
|
||||
git config core.hooksPath "ui/.husky"
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Code Review Setup - Prowler UI
|
||||
|
||||
Guide to set up automatic code validation with Claude Code in the commit hook.
|
||||
Guide to set up automatic code validation with Claude Code in the pre-commit hook.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -35,7 +35,7 @@ In `/ui/.env`, find the "Code Review Configuration" section:
|
||||
|
||||
```bash
|
||||
#### Code Review Configuration ####
|
||||
# Enable Claude Code standards validation on commit hook
|
||||
# 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'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Code Review System Documentation
|
||||
|
||||
Complete documentation for the Claude Code-powered commit validation system.
|
||||
Complete documentation for the Claude Code-powered pre-commit validation system.
|
||||
|
||||
## Quick Navigation
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"lint:fix": "eslint . --fix",
|
||||
"format:check": "./node_modules/.bin/prettier --check ./app",
|
||||
"format:write": "./node_modules/.bin/prettier --config .prettierrc.json --write ./app",
|
||||
"prepare": "husky",
|
||||
"test": "vitest",
|
||||
"test:run": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
@@ -155,7 +156,9 @@
|
||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||
"eslint-plugin-unused-imports": "4.3.0",
|
||||
"globals": "17.0.0",
|
||||
"husky": "9.1.7",
|
||||
"jsdom": "27.4.0",
|
||||
"lint-staged": "15.5.2",
|
||||
"postcss": "8.4.38",
|
||||
"prettier": "3.6.2",
|
||||
"prettier-plugin-tailwindcss": "0.6.14",
|
||||
|
||||
284
ui/pnpm-lock.yaml
generated
284
ui/pnpm-lock.yaml
generated
@@ -414,9 +414,15 @@ importers:
|
||||
globals:
|
||||
specifier: 17.0.0
|
||||
version: 17.0.0
|
||||
husky:
|
||||
specifier: 9.1.7
|
||||
version: 9.1.7
|
||||
jsdom:
|
||||
specifier: 27.4.0
|
||||
version: 27.4.0(@noble/hashes@1.8.0)
|
||||
lint-staged:
|
||||
specifier: 15.5.2
|
||||
version: 15.5.2
|
||||
postcss:
|
||||
specifier: 8.4.38
|
||||
version: 8.4.38
|
||||
@@ -1889,183 +1895,155 @@ packages:
|
||||
resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.0.5':
|
||||
resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-arm@1.2.4':
|
||||
resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-ppc64@1.2.4':
|
||||
resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-riscv64@1.2.4':
|
||||
resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.0.4':
|
||||
resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-s390x@1.2.4':
|
||||
resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.0.4':
|
||||
resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linux-x64@1.2.4':
|
||||
resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.0.4':
|
||||
resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-arm64@1.2.4':
|
||||
resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.0.4':
|
||||
resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-libvips-linuxmusl-x64@1.2.4':
|
||||
resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linux-arm64@0.33.5':
|
||||
resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.33.5':
|
||||
resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-arm@0.34.5':
|
||||
resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-ppc64@0.34.5':
|
||||
resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-riscv64@0.34.5':
|
||||
resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.33.5':
|
||||
resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-s390x@0.34.5':
|
||||
resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.33.5':
|
||||
resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linux-x64@0.34.5':
|
||||
resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.33.5':
|
||||
resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-arm64@0.34.5':
|
||||
resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.33.5':
|
||||
resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-linuxmusl-x64@0.34.5':
|
||||
resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@img/sharp-wasm32@0.33.5':
|
||||
resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==}
|
||||
@@ -2289,28 +2267,24 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-arm64-musl@16.1.6':
|
||||
resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-linux-x64-gnu@16.1.6':
|
||||
resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@next/swc-linux-x64-musl@16.1.6':
|
||||
resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@next/swc-win32-arm64-msvc@16.1.6':
|
||||
resolution: {integrity: sha512-gQmm8izDTPgs+DCWH22kcDmuUp7NyiJgEl18bcr8irXA5N2m2O+JQIr6f3ct42GOs9c0h8QF3L5SzIxcYAAXXw==}
|
||||
@@ -4161,79 +4135,66 @@ packages:
|
||||
resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.59.0':
|
||||
resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-loong64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.59.0':
|
||||
resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.59.0':
|
||||
resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@rollup/rollup-openbsd-x64@4.59.0':
|
||||
resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}
|
||||
@@ -4702,28 +4663,24 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-arm64-musl@4.1.18':
|
||||
resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-gnu@4.1.18':
|
||||
resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@tailwindcss/oxide-linux-x64-musl@4.1.18':
|
||||
resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
|
||||
engines: {node: '>= 10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@tailwindcss/oxide-wasm32-wasi@4.1.18':
|
||||
resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
|
||||
@@ -5145,49 +5102,41 @@ packages:
|
||||
resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-arm64-musl@1.11.1':
|
||||
resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@unrs/resolver-binding-linux-ppc64-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-riscv64-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-riscv64-musl@1.11.1':
|
||||
resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@unrs/resolver-binding-linux-s390x-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-x64-gnu@1.11.1':
|
||||
resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
'@unrs/resolver-binding-linux-x64-musl@1.11.1':
|
||||
resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
'@unrs/resolver-binding-wasm32-wasi@1.11.1':
|
||||
resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==}
|
||||
@@ -5391,6 +5340,10 @@ packages:
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4
|
||||
|
||||
ansi-escapes@7.2.0:
|
||||
resolution: {integrity: sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
ansi-regex@5.0.1:
|
||||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -5643,6 +5596,10 @@ packages:
|
||||
resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
cli-truncate@4.0.0:
|
||||
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
cli-width@4.1.0:
|
||||
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
|
||||
engines: {node: '>= 12'}
|
||||
@@ -5691,6 +5648,9 @@ packages:
|
||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||
engines: {node: '>=12.5.0'}
|
||||
|
||||
colorette@2.0.20:
|
||||
resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
|
||||
|
||||
comma-separated-tokens@2.0.3:
|
||||
resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==}
|
||||
|
||||
@@ -5698,6 +5658,10 @@ packages:
|
||||
resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
commander@13.1.0:
|
||||
resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
commander@14.0.2:
|
||||
resolution: {integrity: sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -6150,6 +6114,10 @@ packages:
|
||||
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
environment@1.1.0:
|
||||
resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
error-ex@1.3.4:
|
||||
resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==}
|
||||
|
||||
@@ -6433,6 +6401,10 @@ packages:
|
||||
resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
execa@8.0.1:
|
||||
resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==}
|
||||
engines: {node: '>=16.17'}
|
||||
|
||||
execa@9.6.1:
|
||||
resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==}
|
||||
engines: {node: ^18.19.0 || >=20.5.0}
|
||||
@@ -6641,6 +6613,10 @@ packages:
|
||||
resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
get-stream@8.0.1:
|
||||
resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
get-stream@9.0.1:
|
||||
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -6822,10 +6798,19 @@ packages:
|
||||
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
|
||||
engines: {node: '>=10.17.0'}
|
||||
|
||||
human-signals@5.0.0:
|
||||
resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==}
|
||||
engines: {node: '>=16.17.0'}
|
||||
|
||||
human-signals@8.0.1:
|
||||
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
|
||||
engines: {node: '>=18.18.0'}
|
||||
|
||||
husky@9.1.7:
|
||||
resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -6962,6 +6947,14 @@ packages:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-fullwidth-code-point@4.0.0:
|
||||
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
is-fullwidth-code-point@5.1.0:
|
||||
resolution: {integrity: sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
is-generator-function@1.1.2:
|
||||
resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -7046,6 +7039,10 @@ packages:
|
||||
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-stream@3.0.0:
|
||||
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
is-stream@4.0.1:
|
||||
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -7294,28 +7291,24 @@ packages:
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-arm64-musl@1.30.2:
|
||||
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-linux-x64-gnu@1.30.2:
|
||||
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [glibc]
|
||||
|
||||
lightningcss-linux-x64-musl@1.30.2:
|
||||
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
libc: [musl]
|
||||
|
||||
lightningcss-win32-arm64-msvc@1.30.2:
|
||||
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
|
||||
@@ -7333,9 +7326,22 @@ packages:
|
||||
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
lilconfig@3.1.3:
|
||||
resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
|
||||
lint-staged@15.5.2:
|
||||
resolution: {integrity: sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==}
|
||||
engines: {node: '>=18.12.0'}
|
||||
hasBin: true
|
||||
|
||||
listr2@8.3.3:
|
||||
resolution: {integrity: sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
loader-runner@4.3.1:
|
||||
resolution: {integrity: sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==}
|
||||
engines: {node: '>=6.11.5'}
|
||||
@@ -7363,6 +7369,10 @@ packages:
|
||||
resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
log-update@6.1.0:
|
||||
resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
longest-streak@3.1.0:
|
||||
resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==}
|
||||
|
||||
@@ -7634,6 +7644,10 @@ packages:
|
||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
mimic-fn@4.0.0:
|
||||
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
mimic-function@5.0.1:
|
||||
resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -7799,6 +7813,10 @@ packages:
|
||||
resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
npm-run-path@5.3.0:
|
||||
resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
npm-run-path@6.0.0:
|
||||
resolution: {integrity: sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -7856,6 +7874,10 @@ packages:
|
||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
onetime@6.0.0:
|
||||
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
onetime@7.0.0:
|
||||
resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -8016,6 +8038,11 @@ packages:
|
||||
resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
pidtree@0.6.0:
|
||||
resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
|
||||
pixelmatch@7.1.0:
|
||||
resolution: {integrity: sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==}
|
||||
hasBin: true
|
||||
@@ -8462,6 +8489,9 @@ packages:
|
||||
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
|
||||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
|
||||
rfdc@1.4.1:
|
||||
resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==}
|
||||
|
||||
robust-predicates@3.0.2:
|
||||
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
|
||||
|
||||
@@ -8620,6 +8650,14 @@ packages:
|
||||
sisteransi@1.0.5:
|
||||
resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==}
|
||||
|
||||
slice-ansi@5.0.0:
|
||||
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
slice-ansi@7.1.2:
|
||||
resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -8667,6 +8705,10 @@ packages:
|
||||
strict-event-emitter@0.5.1:
|
||||
resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
|
||||
|
||||
string-argv@0.3.2:
|
||||
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
||||
engines: {node: '>=0.6.19'}
|
||||
|
||||
string-width@4.2.3:
|
||||
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -8725,6 +8767,10 @@ packages:
|
||||
resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
strip-final-newline@3.0.0:
|
||||
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
strip-final-newline@4.0.0:
|
||||
resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -9350,6 +9396,10 @@ packages:
|
||||
resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
wrap-ansi@9.0.2:
|
||||
resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
@@ -16235,6 +16285,10 @@ snapshots:
|
||||
react: 19.2.4
|
||||
react-dom: 19.2.4(react@19.2.4)
|
||||
|
||||
ansi-escapes@7.2.0:
|
||||
dependencies:
|
||||
environment: 1.1.0
|
||||
|
||||
ansi-regex@5.0.1: {}
|
||||
|
||||
ansi-regex@6.2.2: {}
|
||||
@@ -16514,6 +16568,11 @@ snapshots:
|
||||
|
||||
cli-spinners@2.9.2: {}
|
||||
|
||||
cli-truncate@4.0.0:
|
||||
dependencies:
|
||||
slice-ansi: 5.0.0
|
||||
string-width: 7.2.0
|
||||
|
||||
cli-width@4.1.0: {}
|
||||
|
||||
client-only@0.0.1: {}
|
||||
@@ -16570,10 +16629,14 @@ snapshots:
|
||||
color-convert: 2.0.1
|
||||
color-string: 1.9.1
|
||||
|
||||
colorette@2.0.20: {}
|
||||
|
||||
comma-separated-tokens@2.0.3: {}
|
||||
|
||||
commander@11.1.0: {}
|
||||
|
||||
commander@13.1.0: {}
|
||||
|
||||
commander@14.0.2: {}
|
||||
|
||||
commander@2.20.3: {}
|
||||
@@ -17006,6 +17069,8 @@ snapshots:
|
||||
|
||||
env-paths@2.2.1: {}
|
||||
|
||||
environment@1.1.0: {}
|
||||
|
||||
error-ex@1.3.4:
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
@@ -17448,6 +17513,18 @@ snapshots:
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 2.0.0
|
||||
|
||||
execa@8.0.1:
|
||||
dependencies:
|
||||
cross-spawn: 7.0.6
|
||||
get-stream: 8.0.1
|
||||
human-signals: 5.0.0
|
||||
is-stream: 3.0.0
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 5.3.0
|
||||
onetime: 6.0.0
|
||||
signal-exit: 4.1.0
|
||||
strip-final-newline: 3.0.0
|
||||
|
||||
execa@9.6.1:
|
||||
dependencies:
|
||||
'@sindresorhus/merge-streams': 4.0.0
|
||||
@@ -17681,6 +17758,8 @@ snapshots:
|
||||
|
||||
get-stream@6.0.1: {}
|
||||
|
||||
get-stream@8.0.1: {}
|
||||
|
||||
get-stream@9.0.1:
|
||||
dependencies:
|
||||
'@sec-ant/readable-stream': 0.4.1
|
||||
@@ -17941,8 +18020,12 @@ snapshots:
|
||||
|
||||
human-signals@2.1.0: {}
|
||||
|
||||
human-signals@5.0.0: {}
|
||||
|
||||
human-signals@8.0.1: {}
|
||||
|
||||
husky@9.1.7: {}
|
||||
|
||||
iconv-lite@0.6.3:
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
@@ -18072,6 +18155,12 @@ snapshots:
|
||||
|
||||
is-fullwidth-code-point@3.0.0: {}
|
||||
|
||||
is-fullwidth-code-point@4.0.0: {}
|
||||
|
||||
is-fullwidth-code-point@5.1.0:
|
||||
dependencies:
|
||||
get-east-asian-width: 1.4.0
|
||||
|
||||
is-generator-function@1.1.2:
|
||||
dependencies:
|
||||
call-bound: 1.0.4
|
||||
@@ -18138,6 +18227,8 @@ snapshots:
|
||||
|
||||
is-stream@2.0.1: {}
|
||||
|
||||
is-stream@3.0.0: {}
|
||||
|
||||
is-stream@4.0.1: {}
|
||||
|
||||
is-string@1.1.1:
|
||||
@@ -18413,8 +18504,34 @@ snapshots:
|
||||
lightningcss-win32-arm64-msvc: 1.30.2
|
||||
lightningcss-win32-x64-msvc: 1.30.2
|
||||
|
||||
lilconfig@3.1.3: {}
|
||||
|
||||
lines-and-columns@1.2.4: {}
|
||||
|
||||
lint-staged@15.5.2:
|
||||
dependencies:
|
||||
chalk: 5.6.2
|
||||
commander: 13.1.0
|
||||
debug: 4.4.3
|
||||
execa: 8.0.1
|
||||
lilconfig: 3.1.3
|
||||
listr2: 8.3.3
|
||||
micromatch: 4.0.8
|
||||
pidtree: 0.6.0
|
||||
string-argv: 0.3.2
|
||||
yaml: 2.8.2
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
listr2@8.3.3:
|
||||
dependencies:
|
||||
cli-truncate: 4.0.0
|
||||
colorette: 2.0.20
|
||||
eventemitter3: 5.0.3
|
||||
log-update: 6.1.0
|
||||
rfdc: 1.4.1
|
||||
wrap-ansi: 9.0.2
|
||||
|
||||
loader-runner@4.3.1: {}
|
||||
|
||||
locate-path@6.0.0:
|
||||
@@ -18436,6 +18553,14 @@ snapshots:
|
||||
chalk: 5.6.2
|
||||
is-unicode-supported: 1.3.0
|
||||
|
||||
log-update@6.1.0:
|
||||
dependencies:
|
||||
ansi-escapes: 7.2.0
|
||||
cli-cursor: 5.0.0
|
||||
slice-ansi: 7.1.2
|
||||
strip-ansi: 7.1.2
|
||||
wrap-ansi: 9.0.2
|
||||
|
||||
longest-streak@3.1.0: {}
|
||||
|
||||
loose-envify@1.4.0:
|
||||
@@ -18936,6 +19061,8 @@ snapshots:
|
||||
|
||||
mimic-fn@2.1.0: {}
|
||||
|
||||
mimic-fn@4.0.0: {}
|
||||
|
||||
mimic-function@5.0.1: {}
|
||||
|
||||
min-indent@1.0.1: {}
|
||||
@@ -19078,6 +19205,10 @@ snapshots:
|
||||
dependencies:
|
||||
path-key: 3.1.1
|
||||
|
||||
npm-run-path@5.3.0:
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
|
||||
npm-run-path@6.0.0:
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
@@ -19143,6 +19274,10 @@ snapshots:
|
||||
dependencies:
|
||||
mimic-fn: 2.1.0
|
||||
|
||||
onetime@6.0.0:
|
||||
dependencies:
|
||||
mimic-fn: 4.0.0
|
||||
|
||||
onetime@7.0.0:
|
||||
dependencies:
|
||||
mimic-function: 5.0.1
|
||||
@@ -19306,6 +19441,8 @@ snapshots:
|
||||
|
||||
picomatch@4.0.3: {}
|
||||
|
||||
pidtree@0.6.0: {}
|
||||
|
||||
pixelmatch@7.1.0:
|
||||
dependencies:
|
||||
pngjs: 7.0.0
|
||||
@@ -19803,6 +19940,8 @@ snapshots:
|
||||
|
||||
reusify@1.1.0: {}
|
||||
|
||||
rfdc@1.4.1: {}
|
||||
|
||||
robust-predicates@3.0.2: {}
|
||||
|
||||
rollup@4.59.0:
|
||||
@@ -20128,6 +20267,16 @@ snapshots:
|
||||
|
||||
sisteransi@1.0.5: {}
|
||||
|
||||
slice-ansi@5.0.0:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
is-fullwidth-code-point: 4.0.0
|
||||
|
||||
slice-ansi@7.1.2:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
is-fullwidth-code-point: 5.1.0
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
source-map-support@0.5.21:
|
||||
@@ -20191,6 +20340,8 @@ snapshots:
|
||||
|
||||
strict-event-emitter@0.5.1: {}
|
||||
|
||||
string-argv@0.3.2: {}
|
||||
|
||||
string-width@4.2.3:
|
||||
dependencies:
|
||||
emoji-regex: 8.0.0
|
||||
@@ -20282,6 +20433,8 @@ snapshots:
|
||||
|
||||
strip-final-newline@2.0.0: {}
|
||||
|
||||
strip-final-newline@3.0.0: {}
|
||||
|
||||
strip-final-newline@4.0.0: {}
|
||||
|
||||
strip-indent@3.0.0:
|
||||
@@ -20932,6 +21085,12 @@ snapshots:
|
||||
string-width: 5.1.2
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
wrap-ansi@9.0.2:
|
||||
dependencies:
|
||||
ansi-styles: 6.2.3
|
||||
string-width: 7.2.0
|
||||
strip-ansi: 7.1.2
|
||||
|
||||
wrappy@1.0.2: {}
|
||||
|
||||
ws@8.19.0: {}
|
||||
@@ -20951,8 +21110,7 @@ snapshots:
|
||||
|
||||
yallist@3.1.1: {}
|
||||
|
||||
yaml@2.8.2:
|
||||
optional: true
|
||||
yaml@2.8.2: {}
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
/**
|
||||
* Setup Git Hooks for Prowler UI
|
||||
*
|
||||
* This script checks if prek is managing git hooks.
|
||||
* If not, it runs the repository's setup script to install prek.
|
||||
* This script checks if Python pre-commit is managing git hooks.
|
||||
* If not, it runs the repository's setup script to install pre-commit.
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
@@ -12,16 +12,16 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* Check if prek framework is managing git hooks
|
||||
* Check if Python pre-commit framework is managing git hooks
|
||||
*/
|
||||
function isPrekInstalled(gitRoot) {
|
||||
function isPreCommitInstalled(gitRoot) {
|
||||
const hookPath = path.join(gitRoot, '.git', 'hooks', 'pre-commit');
|
||||
|
||||
try {
|
||||
if (!fs.existsSync(hookPath)) return false;
|
||||
|
||||
const content = fs.readFileSync(hookPath, 'utf8');
|
||||
return content.includes('prek') || content.includes('pre-commit') || content.includes('INSTALL_PYTHON');
|
||||
return content.includes('pre-commit') || content.includes('INSTALL_PYTHON');
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
@@ -72,24 +72,23 @@ if (!gitRoot) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (isPrekInstalled(gitRoot)) {
|
||||
console.log('✅ Git hooks managed by prek framework');
|
||||
console.log(' UI hooks will be called automatically for UI files');
|
||||
if (isPreCommitInstalled(gitRoot)) {
|
||||
console.log('✅ Git hooks managed by Python pre-commit framework');
|
||||
console.log(' Husky hooks will be called automatically for UI files');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Prek not installed - set it up
|
||||
console.log('⚠️ Prek hooks not installed');
|
||||
console.log('📦 Installing prek hooks...');
|
||||
// Pre-commit not installed - set it up
|
||||
console.log('⚠️ Pre-commit hooks not installed');
|
||||
console.log('📦 Installing pre-commit hooks from project dependencies...');
|
||||
console.log('');
|
||||
|
||||
try {
|
||||
runSetupScript(gitRoot);
|
||||
console.log('');
|
||||
console.log('✅ Prek hooks installed successfully');
|
||||
console.log('✅ Pre-commit hooks installed successfully');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to setup git hooks');
|
||||
console.error(' Please run manually from repo root: ./scripts/setup-git-hooks.sh');
|
||||
console.error(' Or install prek manually: https://prek.j178.dev/installation/');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user