Compare commits

...

14 Commits

Author SHA1 Message Date
Prowler Bot d7047cee7a chore(release): Bump versions to v5.27.2 (#11289)
Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com>
2026-05-21 14:48:48 +02:00
Prowler Bot 5487372c99 ci(api): simplify SDK release pin to a single uv lock --upgrade-package (#11288)
Co-authored-by: César Arroba <19954079+cesararroba@users.noreply.github.com>
2026-05-21 13:59:52 +02:00
Prowler Bot ea34d34876 fix(api): chown src/backend and docker-entrypoint to prowler user (#11285)
Co-authored-by: César Arroba <19954079+cesararroba@users.noreply.github.com>
2026-05-21 13:23:43 +02:00
Prowler Bot f3d0f55d52 chore: set SDK changelog version for fixes (#11283)
Co-authored-by: César Arroba <19954079+cesararroba@users.noreply.github.com>
Co-authored-by: César Arroba <cesar@prowler.com>
2026-05-21 12:38:24 +02:00
Prowler Bot 50492e2d6f chore(security): add osv-scanner findings for markdown & pyjwt (#11264)
Co-authored-by: Pedro Martín <pedromarting3@gmail.com>
2026-05-21 08:58:50 +02:00
Pepe Fagoaga 7b190f01c8 fix(versions): use v5.27.1 for SDK 2026-05-20 11:49:35 +02:00
Prowler Bot abebbeea20 fix(api): build container with latest SDK version for release (#11252)
Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
2026-05-20 11:44:33 +02:00
Prowler Bot a835843cc7 fix(api): uv.lock permissions during docker build (#11245)
Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
Co-authored-by: Adrián Jesús Peña Rodríguez <adrianjpr@gmail.com>
2026-05-20 09:49:14 +02:00
Prowler Bot a7f4f44e7b fix(docker): chown copied files to prowler pin uv sync --locked (#11242)
Co-authored-by: Pedro Martín <pedromarting3@gmail.com>
2026-05-19 18:13:19 +02:00
Prowler Bot 2a31bfc3e6 chore(stepsecurity): add missing endpoints (#11241)
Co-authored-by: Pedro Martín <pedromarting3@gmail.com>
2026-05-19 18:11:52 +02:00
Prowler Bot 1a4cfd81c5 fix(azure): skip system 'master' DB in sqlserver_tde_encrypted_with_cmk (#11235)
Co-authored-by: Pedro Martín <pedromarting3@gmail.com>
2026-05-19 17:05:35 +02:00
Prowler Bot c0559e7f10 fix(s3): only emit shadow-resource finding when bucket name matches a predictable pattern (#11237)
Co-authored-by: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com>
2026-05-19 15:53:59 +01:00
Prowler Bot 706742e6dc chore(release): Bump versions to v5.27.1 (#11226)
Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com>
2026-05-19 15:11:49 +02:00
Prowler Bot baaf56ea5e chore(api): Update prowler dependency to v5.27 for release 5.27.0 (#11219)
Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com>
2026-05-19 12:17:44 +02:00
23 changed files with 384 additions and 48 deletions
+1 -1
View File
@@ -145,7 +145,7 @@ SENTRY_RELEASE=local
NEXT_PUBLIC_SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT}
#### Prowler release version ####
NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v5.27.0
NEXT_PUBLIC_PROWLER_RELEASE_VERSION=v5.27.2
# Social login credentials
SOCIAL_GOOGLE_OAUTH_CALLBACK_URL="${AUTH_URL}/api/auth/callback/google"
+10 -4
View File
@@ -122,6 +122,7 @@ jobs:
github.com:443
powershellinfraartifacts-gkhedzdeaghdezhr.z01.azurefd.net:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
pypi.org:443
registry-1.docker.io:443
release-assets.githubusercontent.com:443
@@ -132,11 +133,15 @@ jobs:
with:
persist-credentials: false
- name: Pin prowler SDK to latest master commit
if: github.event_name == 'push'
- name: Refresh prowler SDK pin to current branch tip
run: |
LATEST_SHA=$(git ls-remote https://github.com/prowler-cloud/prowler.git refs/heads/master | cut -f1)
sed -i "s|prowler-cloud/prowler.git@master|prowler-cloud/prowler.git@${LATEST_SHA}|" api/pyproject.toml
# api/pyproject.toml has `@master` on master and `@v5.X` on release
# branches (set by prepare-release.yml). uv lock --upgrade-package
# re-resolves whichever ref is present against the current branch tip
# and writes the SHA into api/uv.lock. The Dockerfile runs
# `uv sync --locked`, which is what actually drives the install.
pip install --no-cache-dir "uv==0.11.14"
(cd api && uv lock --upgrade-package prowler)
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
@@ -179,6 +184,7 @@ jobs:
registry-1.docker.io:443
auth.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
@@ -83,6 +83,7 @@ jobs:
registry-1.docker.io:443
auth.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
debian.map.fastlydns.net:80
release-assets.githubusercontent.com:443
objects.githubusercontent.com:443
+33
View File
@@ -139,6 +139,17 @@ jobs:
sed -i "s|version = \"${CURRENT_API_VERSION}\"|version = \"${NEXT_API_VERSION}\"|" api/pyproject.toml
sed -i "s| version: ${CURRENT_API_VERSION}| version: ${NEXT_API_VERSION}|" api/src/backend/api/specs/v1.yaml
- name: Regenerate lockfiles after version bump
run: |
set -e
# The bumps above edit pyproject.toml / api/pyproject.toml but leave
# uv.lock / api/uv.lock stale, which makes `uv sync --locked` fail in
# the container builds. Refresh both with the uv version the images
# pin (plain `uv lock`, no --upgrade: only the version line changes).
pip install --no-cache-dir "uv==0.11.14"
uv lock
(cd api && uv lock)
- name: Bump UI version (.env)
run: |
set -e
@@ -240,6 +251,17 @@ jobs:
sed -i "s|version = \"${CURRENT_API_VERSION}\"|version = \"${FIRST_API_PATCH_VERSION}\"|" api/pyproject.toml
sed -i "s| version: ${CURRENT_API_VERSION}| version: ${FIRST_API_PATCH_VERSION}|" api/src/backend/api/specs/v1.yaml
- name: Regenerate lockfiles after version bump
run: |
set -e
# The bumps above edit pyproject.toml / api/pyproject.toml but leave
# uv.lock / api/uv.lock stale, which makes `uv sync --locked` fail in
# the container builds. Refresh both with the uv version the images
# pin (plain `uv lock`, no --upgrade: only the version line changes).
pip install --no-cache-dir "uv==0.11.14"
uv lock
(cd api && uv lock)
- name: Bump UI version (.env)
run: |
set -e
@@ -341,6 +363,17 @@ jobs:
sed -i "s|version = \"${CURRENT_API_VERSION}\"|version = \"${NEXT_API_PATCH_VERSION}\"|" api/pyproject.toml
sed -i "s| version: ${CURRENT_API_VERSION}| version: ${NEXT_API_PATCH_VERSION}|" api/src/backend/api/specs/v1.yaml
- name: Regenerate lockfiles after version bump
run: |
set -e
# The bumps above edit pyproject.toml / api/pyproject.toml but leave
# uv.lock / api/uv.lock stale, which makes `uv sync --locked` fail in
# the container builds. Refresh both with the uv version the images
# pin (plain `uv lock`, no --upgrade: only the version line changes).
pip install --no-cache-dir "uv==0.11.14"
uv lock
(cd api && uv lock)
- name: Bump UI version (.env)
run: |
set -e
@@ -114,6 +114,7 @@ jobs:
registry-1.docker.io:443
auth.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
ghcr.io:443
pkg-containers.githubusercontent.com:443
files.pythonhosted.org:443
@@ -171,6 +172,7 @@ jobs:
registry-1.docker.io:443
auth.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
github.com:443
release-assets.githubusercontent.com:443
@@ -149,6 +149,7 @@ jobs:
public.ecr.aws:443
registry-1.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
auth.docker.io:443
debian.map.fastlydns.net:80
github.com:443
@@ -216,6 +217,7 @@ jobs:
auth.docker.io:443
public.ecr.aws:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
github.com:443
release-assets.githubusercontent.com:443
api.ecr-public.us-east-1.amazonaws.com:443
@@ -85,6 +85,7 @@ jobs:
registry-1.docker.io:443
auth.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
api.github.com:443
mirror.gcr.io:443
check.trivy.dev:443
+1
View File
@@ -46,6 +46,7 @@ jobs:
schema.ocsf.io:443
registry-1.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
powershellinfraartifacts-gkhedzdeaghdezhr.z01.azurefd.net:443
o26192.ingest.us.sentry.io:443
management.azure.com:443
@@ -116,6 +116,7 @@ jobs:
allowed-endpoints: >
registry-1.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
auth.docker.io:443
registry.npmjs.org:443
dl-cdn.alpinelinux.org:443
@@ -172,6 +173,7 @@ jobs:
registry-1.docker.io:443
auth.docker.io:443
production.cloudflare.docker.com:443
production.cloudfront.docker.com:443
- name: Login to DockerHub
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
+6 -6
View File
@@ -76,11 +76,11 @@ USER prowler
WORKDIR /home/prowler
# Copy necessary files
COPY prowler/ /home/prowler/prowler/
COPY dashboard/ /home/prowler/dashboard/
COPY pyproject.toml uv.lock /home/prowler/
COPY README.md /home/prowler/
COPY prowler/providers/m365/lib/powershell/m365_powershell.py /home/prowler/prowler/providers/m365/lib/powershell/m365_powershell.py
COPY --chown=prowler:prowler prowler/ /home/prowler/prowler/
COPY --chown=prowler:prowler dashboard/ /home/prowler/dashboard/
COPY --chown=prowler:prowler pyproject.toml uv.lock /home/prowler/
COPY --chown=prowler:prowler README.md /home/prowler/
COPY --chown=prowler:prowler prowler/providers/m365/lib/powershell/m365_powershell.py /home/prowler/prowler/providers/m365/lib/powershell/m365_powershell.py
# Install Python dependencies
ENV HOME='/home/prowler'
@@ -89,7 +89,7 @@ ENV PATH="${HOME}/.local/bin:${PATH}"
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir uv==0.11.14
RUN uv sync --compile-bytecode && \
RUN uv sync --locked --compile-bytecode && \
rm -rf ~/.cache/uv
# Install PowerShell modules
+4 -4
View File
@@ -89,7 +89,7 @@ WORKDIR /home/prowler
# Ensure output directory exists
RUN mkdir -p /tmp/prowler_api_output
COPY pyproject.toml uv.lock ./
COPY --chown=prowler:prowler pyproject.toml uv.lock ./
RUN pip install --no-cache-dir --upgrade pip && \
pip install --no-cache-dir uv==0.11.14
@@ -97,13 +97,13 @@ RUN pip install --no-cache-dir --upgrade pip && \
ENV PATH="/home/prowler/.local/bin:$PATH"
# Add `--no-install-project` to avoid installing the current project as a package
RUN uv sync --no-install-project && \
RUN uv sync --locked --no-install-project && \
rm -rf ~/.cache/uv
RUN .venv/bin/python .venv/lib/python3.12/site-packages/prowler/providers/m365/lib/powershell/m365_powershell.py
COPY src/backend/ ./backend/
COPY docker-entrypoint.sh ./docker-entrypoint.sh
COPY --chown=prowler:prowler src/backend/ ./backend/
COPY --chown=prowler:prowler docker-entrypoint.sh ./docker-entrypoint.sh
WORKDIR /home/prowler/backend
+2 -2
View File
@@ -43,7 +43,7 @@ dependencies = [
"defusedxml==0.7.1",
"gunicorn==23.0.0",
"lxml==6.1.0",
"prowler @ git+https://github.com/prowler-cloud/prowler.git@master",
"prowler @ git+https://github.com/prowler-cloud/prowler.git@v5.27",
"psycopg2-binary==2.9.9",
"pytest-celery[redis] (==1.3.0)",
"sentry-sdk[django] (==2.56.0)",
@@ -68,7 +68,7 @@ name = "prowler-api"
package-mode = false
# Needed for the SDK compatibility
requires-python = ">=3.11,<3.13"
version = "1.28.0"
version = "1.28.2"
[tool.uv]
# Transitive pins matching master to avoid silent drift; bump deliberately.
+1 -1
View File
@@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: Prowler API
version: 1.28.0
version: 1.28.2
description: |-
Prowler API specification.
Generated
+5 -4
View File
@@ -4410,8 +4410,8 @@ wheels = [
[[package]]
name = "prowler"
version = "5.27.0"
source = { git = "https://github.com/prowler-cloud/prowler.git?rev=master#0abbb7fc590eaf7de6ed354dd5a217bca261d2b0" }
version = "5.27.1"
source = { git = "https://github.com/prowler-cloud/prowler.git?rev=v5.27#abebbeea20fe2ba616e6a3bbfc9e7f2931b24d95" }
dependencies = [
{ name = "alibabacloud-actiontrail20200706" },
{ name = "alibabacloud-credentials" },
@@ -4484,6 +4484,7 @@ dependencies = [
{ name = "pygithub" },
{ name = "python-dateutil" },
{ name = "pytz" },
{ name = "scaleway" },
{ name = "schema" },
{ name = "shodan" },
{ name = "slack-sdk" },
@@ -4494,7 +4495,7 @@ dependencies = [
[[package]]
name = "prowler-api"
version = "1.28.0"
version = "1.28.2"
source = { virtual = "." }
dependencies = [
{ name = "cartography" },
@@ -4590,7 +4591,7 @@ requires-dist = [
{ name = "matplotlib", specifier = "==3.10.8" },
{ name = "neo4j", specifier = "==6.1.0" },
{ name = "openai", specifier = "==1.109.1" },
{ name = "prowler", git = "https://github.com/prowler-cloud/prowler.git?rev=master" },
{ name = "prowler", git = "https://github.com/prowler-cloud/prowler.git?rev=v5.27" },
{ name = "psycopg2-binary", specifier = "==2.9.9" },
{ name = "pytest-celery", extras = ["redis"], specifier = "==1.3.0" },
{ name = "reportlab", specifier = "==4.4.10" },
+30
View File
@@ -0,0 +1,30 @@
# osv-scanner per-vulnerability ignore list.
#
# Each [[IgnoredVulns]] entry must include a `reason` explaining why the
# finding is accepted and an `ignoreUntil` date so the suppression auto-expires
# and gets re-evaluated. See https://github.com/google/osv-scanner for the
# config schema.
[[IgnoredVulns]]
id = "PYSEC-2025-183"
ignoreUntil = 2026-08-20T00:00:00Z
reason = """
CVE-2025-45768 is disputed by the pyjwt maintainers. The advisory describes
weak encryption, but the underlying issue is that callers may pick a short
HMAC secret — key-length enforcement is the application's responsibility, not
a defect in the library. We are on pyjwt 2.12.1 (latest at pin time) and
enforce key strength in our own auth code, so this advisory does not apply.
Re-evaluate when a non-disputed advisory or upstream fix lands.
"""
[[IgnoredVulns]]
id = "PYSEC-2026-89"
ignoreUntil = 2026-08-20T00:00:00Z
reason = """
False positive caused by a malformed PYSEC record. The equivalent GitHub
Security Advisory (GHSA-5wmx-573v-2qwq) for CVE-2025-69534 declares the issue
fixed in markdown 3.8.1. We are on markdown==3.10.2 (latest release, includes
the fix), but the PYSEC entry's range is [{introduced: "0"}, {}] with no
closing "fixed" event, so osv-scanner flags every version. There is no newer
release to upgrade to. Re-evaluate once the PYSEC record is corrected upstream.
"""
+9
View File
@@ -2,6 +2,15 @@
All notable changes to the **Prowler SDK** are documented in this file.
## [5.27.1] (Prowler v5.27.1)
### 🐞 Fixed
- `s3_bucket_shadow_resource_vulnerability` no longer emits a tautological `PASS` finding for every bucket; a finding is now produced only when the bucket name matches one of the predictable service patterns (Glue, SageMaker, EMR, CodeStar) [(#11220)](https://github.com/prowler-cloud/prowler/pull/11220)
- `sqlserver_tde_encrypted_with_cmk` check for Azure provider no longer reports a false `FAIL` for SQL Servers whose user databases are correctly encrypted with a customer-managed key, by excluding the system `master` database (always reports TDE `Disabled` and is not customer-controllable) from the TDE evaluation [(#11233)](https://github.com/prowler-cloud/prowler/pull/11233)
---
## [5.27.0] (Prowler v5.27.0)
### 🚀 Added
+1 -1
View File
@@ -48,7 +48,7 @@ class _MutableTimestamp:
timestamp = _MutableTimestamp(datetime.today())
timestamp_utc = _MutableTimestamp(datetime.now(timezone.utc))
prowler_version = "5.27.0"
prowler_version = "5.27.2"
html_logo_url = "https://github.com/prowler-cloud/prowler/"
square_logo_img = "https://raw.githubusercontent.com/prowler-cloud/prowler/dc7d2d5aeb92fdf12e8604f42ef6472cd3e8e889/docs/img/prowler-logo-black.png"
aws_logo = "https://user-images.githubusercontent.com/38561120/235953920-3e3fba08-0795-41dc-b480-9bea57db9f2e.png"
@@ -24,30 +24,30 @@ class s3_bucket_shadow_resource_vulnerability(Check):
# First, check buckets in the current account
for bucket in s3_client.buckets.values():
report = Check_Report_AWS(self.metadata(), resource=bucket)
report.region = bucket.region
report.resource_id = bucket.name
report.resource_arn = bucket.arn
report.resource_tags = bucket.tags
report.status = "PASS"
report.status_extended = (
f"S3 bucket {bucket.name} is not a known shadow resource."
)
# Check if this bucket matches any predictable pattern
# Only emit a finding when the bucket name actually matches one of
# the predictable service patterns. A bucket whose name does not
# match any pattern is, by definition, not a shadow resource, so a
# PASS finding for it would be tautological and add no signal.
for service, pattern_format in predictable_patterns.items():
pattern = pattern_format.replace("<region>", bucket.region)
if re.match(pattern, bucket.name):
report = Check_Report_AWS(self.metadata(), resource=bucket)
report.region = bucket.region
report.resource_id = bucket.name
report.resource_arn = bucket.arn
report.resource_tags = bucket.tags
if bucket.owner_id != s3_client.audited_canonical_id:
report.status = "FAIL"
report.status_extended = f"S3 bucket {bucket.name} for service {service} is a known shadow resource and it is owned by another account ({bucket.owner_id})."
else:
report.status = "PASS"
report.status_extended = f"S3 bucket {bucket.name} for service {service} is a known shadow resource but it is correctly owned by the audited account."
findings.append(report)
reported_buckets.add(bucket.name)
break
findings.append(report)
reported_buckets.add(bucket.name)
# Now check for shadow resources in other accounts by testing predictable patterns
# We'll test different regions to see if shadow resources exist
@@ -10,9 +10,13 @@ class sqlserver_tde_encrypted_with_cmk(Check):
subscription, subscription
)
for sql_server in sql_servers:
databases = (
sql_server.databases if sql_server.databases is not None else []
)
databases = [
database
for database in (
sql_server.databases if sql_server.databases is not None else []
)
if database.name.lower() != "master"
]
if len(databases) > 0:
report = Check_Report_Azure(
metadata=self.metadata(), resource=sql_server
+1 -1
View File
@@ -120,7 +120,7 @@ maintainers = [{name = "Prowler Engineering", email = "engineering@prowler.com"}
name = "prowler"
readme = "README.md"
requires-python = ">=3.10,<3.13"
version = "5.27.0"
version = "5.27.2"
[project.scripts]
prowler = "prowler.__main__:prowler"
@@ -93,6 +93,8 @@ class Test_s3_bucket_shadow_resource_vulnerability:
@mock_aws
def test_bucket_not_predictable(self):
# A bucket whose name does not match any predictable service pattern
# is not a shadow resource and must not produce any finding.
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
aws_provider.identity.identity_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root"
@@ -113,6 +115,55 @@ class Test_s3_bucket_shadow_resource_vulnerability:
s3_client.provider = aws_provider
s3_client._head_bucket = mock.MagicMock(return_value=False)
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=aws_provider,
),
mock.patch(
"prowler.providers.aws.services.s3.s3_bucket_shadow_resource_vulnerability.s3_bucket_shadow_resource_vulnerability.s3_client",
new=s3_client,
),
):
from prowler.providers.aws.services.s3.s3_bucket_shadow_resource_vulnerability.s3_bucket_shadow_resource_vulnerability import (
s3_bucket_shadow_resource_vulnerability,
)
check = s3_bucket_shadow_resource_vulnerability()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_only_predictable_bucket_reported_among_many(self):
# With a mix of buckets, only the one matching a predictable pattern
# must produce a finding; the rest must be silent.
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
aws_provider.identity.identity_arn = f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:root"
predictable_bucket = f"sagemaker-{AWS_REGION_US_EAST_1}-{AWS_ACCOUNT_NUMBER}"
plain_buckets = [
"config-bucket-data",
"my-app-data-bucket",
"guardduty-findings-store",
]
s3_client = mock.MagicMock()
s3_client.audited_canonical_id = AWS_ACCOUNT_NUMBER
s3_client.audited_partition = "aws"
s3_client.buckets = {
name: Bucket(
name=name,
arn=f"arn:aws:s3:::{name}",
region=AWS_REGION_US_EAST_1,
owner_id=AWS_ACCOUNT_NUMBER,
tags=[],
)
for name in [predictable_bucket, *plain_buckets]
}
s3_client.provider = aws_provider
s3_client._head_bucket = mock.MagicMock(return_value=False)
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -132,14 +183,10 @@ class Test_s3_bucket_shadow_resource_vulnerability:
assert len(result) == 1
report = result[0]
# Test all report attributes
assert report.status == "PASS"
assert report.region == AWS_REGION_US_EAST_1
assert report.resource_id == bucket_name
assert report.resource_arn == f"arn:aws:s3:::{bucket_name}"
assert report.resource_tags == [{"Key": "Project", "Value": "test-project"}]
assert "is not a known shadow resource" in report.status_extended
assert report.resource_id == predictable_bucket
assert "SageMaker" in report.status_extended
assert "is correctly owned by the audited account" in report.status_extended
@mock_aws
def test_shadow_resource_in_other_account(self):
@@ -264,3 +264,200 @@ class Test_sqlserver_tde_encrypted_with_cmk:
assert result[0].resource_name == sql_server_name
assert result[0].resource_id == sql_server_id
assert result[0].location == "location"
def test_sql_servers_master_database_disabled_user_database_enabled(self):
# System "master" database always reports TDE Disabled in Azure SQL
# and is not customer-controllable. It must not fail a server whose
# user databases are correctly encrypted with CMK (PROWLER-1760).
sqlserver_client = mock.MagicMock
sqlserver_client.subscriptions = {
AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME
}
sql_server_name = "SQL Server Name"
sql_server_id = str(uuid4())
master_database = Database(
id="master_id",
name="master",
type="type",
location="location",
managed_by="managed_by",
tde_encryption=TransparentDataEncryption(status="Disabled"),
)
user_database = Database(
id="user_id",
name="DynamicBudgets_Intacct",
type="type",
location="location",
managed_by="managed_by",
tde_encryption=TransparentDataEncryption(status="Enabled"),
)
sqlserver_client.sql_servers = {
AZURE_SUBSCRIPTION_ID: [
Server(
id=sql_server_id,
name=sql_server_name,
location="location",
public_network_access="",
minimal_tls_version="",
administrators=None,
auditing_policies=None,
firewall_rules=None,
databases=[master_database, user_database],
encryption_protector=EncryptionProtector(
server_key_type="AzureKeyVault"
),
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client",
new=sqlserver_client,
),
):
from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import (
sqlserver_tde_encrypted_with_cmk,
)
check = sqlserver_tde_encrypted_with_cmk()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"SQL Server {sql_server_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} has TDE enabled with CMK."
)
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
assert result[0].resource_name == sql_server_name
assert result[0].resource_id == sql_server_id
assert result[0].location == "location"
def test_sql_servers_only_master_database(self):
# A server whose only database is the system "master" has no user
# databases to evaluate, so it must not produce a finding.
sqlserver_client = mock.MagicMock
sqlserver_client.subscriptions = {
AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME
}
sql_server_name = "SQL Server Name"
sql_server_id = str(uuid4())
master_database = Database(
id="master_id",
name="MASTER",
type="type",
location="location",
managed_by="managed_by",
tde_encryption=TransparentDataEncryption(status="Disabled"),
)
sqlserver_client.sql_servers = {
AZURE_SUBSCRIPTION_ID: [
Server(
id=sql_server_id,
name=sql_server_name,
location="location",
public_network_access="",
minimal_tls_version="",
administrators=None,
auditing_policies=None,
firewall_rules=None,
databases=[master_database],
encryption_protector=EncryptionProtector(
server_key_type="AzureKeyVault"
),
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client",
new=sqlserver_client,
),
):
from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import (
sqlserver_tde_encrypted_with_cmk,
)
check = sqlserver_tde_encrypted_with_cmk()
result = check.execute()
assert len(result) == 0
def test_sql_servers_master_disabled_user_database_disabled(self):
# Filtering out "master" must not mask a genuinely failing user
# database: a disabled user DB still fails even with CMK.
sqlserver_client = mock.MagicMock
sqlserver_client.subscriptions = {
AZURE_SUBSCRIPTION_ID: AZURE_SUBSCRIPTION_NAME
}
sql_server_name = "SQL Server Name"
sql_server_id = str(uuid4())
master_database = Database(
id="master_id",
name="master",
type="type",
location="location",
managed_by="managed_by",
tde_encryption=TransparentDataEncryption(status="Disabled"),
)
user_database = Database(
id="user_id",
name="DynamicBudgets_Intacct",
type="type",
location="location",
managed_by="managed_by",
tde_encryption=TransparentDataEncryption(status="Disabled"),
)
sqlserver_client.sql_servers = {
AZURE_SUBSCRIPTION_ID: [
Server(
id=sql_server_id,
name=sql_server_name,
location="location",
public_network_access="",
minimal_tls_version="",
administrators=None,
auditing_policies=None,
firewall_rules=None,
databases=[master_database, user_database],
encryption_protector=EncryptionProtector(
server_key_type="AzureKeyVault"
),
)
]
}
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_azure_provider(),
),
mock.patch(
"prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk.sqlserver_client",
new=sqlserver_client,
),
):
from prowler.providers.azure.services.sqlserver.sqlserver_tde_encrypted_with_cmk.sqlserver_tde_encrypted_with_cmk import (
sqlserver_tde_encrypted_with_cmk,
)
check = sqlserver_tde_encrypted_with_cmk()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"SQL Server {sql_server_name} from subscription {AZURE_SUBSCRIPTION_DISPLAY} has TDE disabled with CMK."
)
assert result[0].subscription == AZURE_SUBSCRIPTION_ID
assert result[0].resource_name == sql_server_name
assert result[0].resource_id == sql_server_id
assert result[0].location == "location"
Generated
+1 -1
View File
@@ -3241,7 +3241,7 @@ wheels = [
[[package]]
name = "prowler"
version = "5.27.0"
version = "5.27.2"
source = { editable = "." }
dependencies = [
{ name = "alibabacloud-actiontrail20200706" },