Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES/7380.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Moved artifact checksum validation from module-level settings code to a Django system check.
63 changes: 62 additions & 1 deletion pulpcore/app/checks.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
from pathlib import Path

from django.conf import settings
from django.core.checks import Error as CheckError, Warning as CheckWarning, register
from django.core.checks import (
Debug as CheckDebug,
Error as CheckError,
Warning as CheckWarning,
Tags,
register,
)
from django.db.models import Q

from pulpcore import constants


@register(deploy=True)
Expand Down Expand Up @@ -56,3 +65,55 @@ def storage_paths(app_configs, **kwargs):
)

return warnings


@register(Tags.database)
def check_artifact_checksums(app_configs, **kwargs):
from pulpcore.app.models import Artifact, RemoteArtifact

messages = []
allowed = set(settings.ALLOWED_CONTENT_CHECKSUMS)
forbidden = set(constants.ALL_KNOWN_CONTENT_CHECKSUMS).difference(allowed)

try:
for checksum in allowed:
if Artifact.objects.filter(**{checksum: None}).exists():
messages.append(
CheckError(
f"There have been identified artifacts missing checksum '{checksum}'. "
"Run 'pulpcore-manager handle-artifact-checksums' first to populate "
"missing artifact checksums.",
id="pulpcore.E002",
)
)
for checksum in forbidden:
if Artifact.objects.exclude(**{checksum: None}).exists():
messages.append(
CheckWarning(
f"There have been identified artifacts with forbidden checksum "
f"'{checksum}'. Run 'pulpcore-manager handle-artifact-checksums' "
"to unset forbidden checksums.",
id="pulpcore.W004",
)
)

has_any_checksum = ~Q(**{c: None for c in constants.ALL_KNOWN_CONTENT_CHECKSUMS})
missing_allowed = Q(**{c: None for c in allowed})
if RemoteArtifact.objects.filter(has_any_checksum & missing_allowed).exists():
messages.append(
CheckWarning(
"Detected remote content without allowed checksums. "
"Run 'pulpcore-manager handle-artifact-checksums --report' to "
"view this content.",
id="pulpcore.W005",
)
)
except Exception:
messages.append(
CheckDebug(
"Skipping artifact checksum checks (table may not exist yet).",
id="pulpcore.D001",
)
)

return messages
66 changes: 0 additions & 66 deletions pulpcore/app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

from cryptography.fernet import Fernet
from django.core.exceptions import ImproperlyConfigured
from django.db import connection
from dynaconf import DjangoDynaconf, Dynaconf, Validator

from pulpcore import constants
Expand Down Expand Up @@ -558,71 +557,6 @@ def otel_middleware_hook(settings):
ALLOWED_CONTENT_CHECKSUMS
)

_SKIPPED_COMMANDS_FOR_CONTENT_CHECKS = [
"handle-artifact-checksums",
"migrate",
"collectstatic",
"openapi",
]

if not (len(sys.argv) >= 2 and sys.argv[1] in _SKIPPED_COMMANDS_FOR_CONTENT_CHECKS):
try:
with connection.cursor() as cursor:
for checksum in ALLOWED_CONTENT_CHECKSUMS:
# can't import Artifact here so use a direct db connection
cursor.execute(
f"SELECT count(pulp_id) FROM core_artifact WHERE {checksum} IS NULL LIMIT 1"
)
row = cursor.fetchone()
if row[0] > 0:
raise ImproperlyConfigured(
(
"There have been identified artifacts missing checksum '{}'. "
"Run 'pulpcore-manager handle-artifact-checksums' first to populate "
"missing artifact checksums."
).format(checksum)
)
for checksum in FORBIDDEN_CHECKSUMS:
# can't import Artifact here so use a direct db connection
cursor.execute(
f"SELECT count(pulp_id) FROM core_artifact WHERE {checksum} IS NOT NULL LIMIT 1"
)
row = cursor.fetchone()
if row[0] > 0:
raise ImproperlyConfigured(
(
"There have been identified artifacts with forbidden checksum '{}'. "
"Run 'pulpcore-manager handle-artifact-checksums' first to unset "
"forbidden checksums."
).format(checksum)
)

# warn if there are remote artifacts with checksums but no allowed checksums
cond = " AND ".join([f"{c} IS NULL" for c in constants.ALL_KNOWN_CONTENT_CHECKSUMS])
no_checksum_query = f"SELECT pulp_id FROM core_remoteartifact WHERE {cond}"
cond = " AND ".join([f"{c} IS NULL" for c in ALLOWED_CONTENT_CHECKSUMS])
cursor.execute(
f"SELECT count(pulp_id) FROM core_remoteartifact WHERE {cond} AND "
f"pulp_id NOT IN ({no_checksum_query}) LIMIT 1"
)
row = cursor.fetchone()
if row[0] > 0:
_logger.warning(
(
"Warning: detected remote content without allowed checksums. "
"Run 'pulpcore-manager handle-artifact-checksums --report' to "
"view this content."
)
)

except ImproperlyConfigured as e:
raise e
except Exception:
# our check could fail if the table hasn't been created yet or we can't get a db connection
pass
finally:
connection.close()

if settings.API_ROOT_REWRITE_HEADER:
api_root = "/<path:api_root>/"
else:
Expand Down