More Checks for System Packages and Configs

This commit is contained in:
Ariel Rin 2024-07-15 11:00:06 +00:00
parent 57ac7a5277
commit db6f4c91dc
3 changed files with 187 additions and 37 deletions

View File

@ -25,7 +25,7 @@ before_script:
pre-commit-check: pre-commit-check:
<<: *only-default <<: *only-default
stage: pre-commit stage: pre-commit
image: python:3.11-bullseye image: python:3.11-bookworm
# variables: # variables:
# PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit # PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
# cache: # cache:
@ -53,7 +53,7 @@ secret_detection:
test-3.8-core: test-3.8-core:
<<: *only-default <<: *only-default
image: python:3.8-bullseye image: python:3.8-bookworm
script: script:
- tox -e py38-core - tox -e py38-core
artifacts: artifacts:
@ -65,7 +65,7 @@ test-3.8-core:
test-3.9-core: test-3.9-core:
<<: *only-default <<: *only-default
image: python:3.9-bullseye image: python:3.9-bookworm
script: script:
- tox -e py39-core - tox -e py39-core
artifacts: artifacts:
@ -77,7 +77,7 @@ test-3.9-core:
test-3.10-core: test-3.10-core:
<<: *only-default <<: *only-default
image: python:3.10-bullseye image: python:3.10-bookworm
script: script:
- tox -e py310-core - tox -e py310-core
artifacts: artifacts:
@ -89,7 +89,7 @@ test-3.10-core:
test-3.11-core: test-3.11-core:
<<: *only-default <<: *only-default
image: python:3.11-bullseye image: python:3.11-bookworm
script: script:
- tox -e py311-core - tox -e py311-core
artifacts: artifacts:
@ -101,7 +101,7 @@ test-3.11-core:
test-3.12-core: test-3.12-core:
<<: *only-default <<: *only-default
image: python:3.12-rc-bullseye image: python:3.12-bookworm
script: script:
- tox -e py312-core - tox -e py312-core
artifacts: artifacts:
@ -113,7 +113,7 @@ test-3.12-core:
test-3.8-all: test-3.8-all:
<<: *only-default <<: *only-default
image: python:3.8-bullseye image: python:3.8-bookworm
script: script:
- tox -e py38-all - tox -e py38-all
artifacts: artifacts:
@ -125,7 +125,7 @@ test-3.8-all:
test-3.9-all: test-3.9-all:
<<: *only-default <<: *only-default
image: python:3.9-bullseye image: python:3.9-bookworm
script: script:
- tox -e py39-all - tox -e py39-all
artifacts: artifacts:
@ -137,7 +137,7 @@ test-3.9-all:
test-3.10-all: test-3.10-all:
<<: *only-default <<: *only-default
image: python:3.10-bullseye image: python:3.10-bookworm
script: script:
- tox -e py310-all - tox -e py310-all
artifacts: artifacts:
@ -149,7 +149,7 @@ test-3.10-all:
test-3.11-all: test-3.11-all:
<<: *only-default <<: *only-default
image: python:3.11-bullseye image: python:3.11-bookworm
script: script:
- tox -e py311-all - tox -e py311-all
artifacts: artifacts:
@ -162,7 +162,7 @@ test-3.11-all:
test-3.12-all: test-3.12-all:
<<: *only-default <<: *only-default
image: python:3.12-rc-bullseye image: python:3.12-bookworm
script: script:
- tox -e py312-all - tox -e py312-all
artifacts: artifacts:
@ -174,7 +174,7 @@ test-3.12-all:
build-test: build-test:
stage: test stage: test
image: python:3.11-bullseye image: python:3.11-bookworm
before_script: before_script:
- python -m pip install --upgrade pip - python -m pip install --upgrade pip
@ -193,13 +193,13 @@ build-test:
test-docs: test-docs:
<<: *only-default <<: *only-default
image: python:3.11-bullseye image: python:3.11-bookworm
script: script:
- tox -e docs - tox -e docs
deploy_production: deploy_production:
stage: deploy stage: deploy
image: python:3.11-bullseye image: python:3.11-bookworm
before_script: before_script:
- python -m pip install --upgrade pip - python -m pip install --upgrade pip

View File

@ -5,26 +5,5 @@ from django.core.checks import Warning, Error, register
class AllianceAuthConfig(AppConfig): class AllianceAuthConfig(AppConfig):
name = 'allianceauth' name = 'allianceauth'
def ready(self) -> None:
@register() import allianceauth.checks # noqa
def check_settings(app_configs, **kwargs):
from django.conf import settings
errors = []
if hasattr(settings, "SITE_URL"):
if settings.SITE_URL[-1] == "/":
errors.append(Warning(
"'SITE_URL' Has a trailing slash. This may lead to incorrect links being generated by Auth."))
else:
errors.append(Error(
"No 'SITE_URL' found is settings. This may lead to incorrect links being generated by Auth or Errors in 3rd party modules."))
if hasattr(settings, "CSRF_TRUSTED_ORIGINS"):
if hasattr(settings, "SITE_URL"):
if settings.SITE_URL not in settings.CSRF_TRUSTED_ORIGINS:
errors.append(Warning(
"'SITE_URL' not found in 'CSRF_TRUSTED_ORIGINS'. Auth may not load pages correctly until this is rectified."))
else:
errors.append(Error(
"No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified"))
return errors

171
allianceauth/checks.py Normal file
View File

@ -0,0 +1,171 @@
from typing import List
from django import db
from django.core.checks import CheckMessage, Error, register, Warning
from allianceauth.utils.cache import get_redis_client
from django.utils import timezone
from packaging.version import InvalidVersion, Version as Pep440Version
from celery import current_app
from django.conf import settings
from sqlite3.dbapi2 import sqlite_version_info
"""
A = System Packages
B = Configuration
"""
@register()
def django_settings(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
if hasattr(settings, "SITE_URL"):
if settings.SITE_URL[-1] == "/":
errors.append(Warning("'SITE_URL' Has a trailing slash. This may lead to incorrect links being generated by Auth.", hint="", id="allianceauth.checks.B005"))
else:
errors.append(Error("No 'SITE_URL' found is settings. This may lead to incorrect links being generated by Auth or Errors in 3rd party modules.", hint="", id="allianceauth.checks.B006"))
if hasattr(settings, "CSRF_TRUSTED_ORIGINS") and hasattr(settings, "SITE_URL"):
if settings.SITE_URL not in settings.CSRF_TRUSTED_ORIGINS:
errors.append(Warning("'SITE_URL' not found in 'CSRF_TRUSTED_ORIGINS'. Auth may not load pages correctly until this is rectified.", hint="", id="allianceauth.checks.B007"))
else:
errors.append(Error("No 'CSRF_TRUSTED_ORIGINS' found is settings, Auth may not load pages correctly until this is rectified", hint="", id="allianceauth.checks.B008"))
return errors
@register()
def system_package_redis(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
try:
redis_version = Pep440Version(get_redis_client().info()['redis_version'])
except InvalidVersion:
errors.append(Warning("Unable to confirm Redis Version"))
return errors
if redis_version.major == 7 and redis_version.minor == 2 and timezone.now() > timezone.datetime(year=2025, month=8, day=31, tzinfo=timezone.utc):
errors.append(Error(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/", id="allianceauth.checks.A001"))
elif redis_version.major == 7 and redis_version.minor == 0:
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/", id="allianceauth.checks.A002"))
elif redis_version.major == 6 and redis_version.minor == 2:
errors.append(Warning(f"Redis {redis_version.public} in Security Support only, Updating Suggested", hint="https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/", id="allianceauth.checks.A018"))
elif redis_version.major in [6, 5]:
errors.append(Error(f"Redis {redis_version.public} EOL", hint="https://redis.io/docs/latest/operate/oss_and_stack/install/install-redis/install-redis-on-linux/", id="allianceauth.checks.A003"))
return errors
@register()
def system_package_mysql(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
for connection in db.connections.all():
if connection.vendor == "mysql":
try:
mysql_version = Pep440Version(".".join(str(i) for i in connection.mysql_version))
except InvalidVersion:
errors.append(Warning("Unable to confirm MySQL Version"))
return errors
# MySQL 8
if mysql_version.major == 8 and mysql_version.minor == 4 and timezone.now() > timezone.datetime(year=2032, month=4, day=30, tzinfo=timezone.utc):
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A004"))
elif mysql_version.major == 8 and mysql_version.minor == 3:
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A005"))
elif mysql_version.major == 8 and mysql_version.minor == 2:
errors.append(Warning(f"MySQL {mysql_version.public} Non LTS", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A006"))
elif mysql_version.major == 8 and mysql_version.minor == 1:
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A007"))
elif mysql_version.major == 8 and mysql_version.minor == 0 and timezone.now() > timezone.datetime(year=2026, month=4, day=30, tzinfo=timezone.utc):
errors.append(Error(f"MySQL {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A008"))
elif mysql_version.major < 8: # This will also catch Mariadb 5.x
errors.append(Error(f"MySQL or MariaDB {mysql_version.public} EOL", hint="https://dev.mysql.com/doc/mysql-apt-repo-quick-guide/en/", id="allianceauth.checks.A009"))
return errors
@register()
def system_package_mariadb(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
for connection in db.connections.all():
if connection.vendor == "mysql": # Still to find a way to determine MySQL vs MariaDB
try:
mariadb_version = Pep440Version(".".join(str(i) for i in connection.mysql_version))
except InvalidVersion:
errors.append(Warning("Unable to confirm MariaDB Version"))
return errors
# MariaDB 11
if mariadb_version.major == 11 and mariadb_version.minor == 4 and timezone.now() > timezone.datetime(year=2029, month=5, day=19, tzinfo=timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A010"))
elif mariadb_version.major == 11 and mariadb_version.minor == 2:
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A018"))
if timezone.now() > timezone.datetime(year=2024, month=11, day=21, tzinfo=timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A011"))
elif mariadb_version.major == 11 and mariadb_version.minor == 1:
errors.append(Warning(f"MariaDB {mariadb_version.public} Non LTS", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A019"))
if timezone.now() > timezone.datetime(year=2024, month=8, day=21, tzinfo=timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A012"))
elif mariadb_version.major == 11 and mariadb_version.minor in [0, 3]: # Demote versions down here once EOL
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A013"))
# MariaDB 10
elif mariadb_version.major == 10 and mariadb_version.minor == 11 and timezone.now() > timezone.datetime(year=2028, month=2, day=10, tzinfo=timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config.", id="allianceauth.checks.A014"))
elif mariadb_version.major == 10 and mariadb_version.minor == 6 and timezone.now() > timezone.datetime(year=2026, month=7, day=6, tzinfo=timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A0015"))
elif mariadb_version.major == 10 and mariadb_version.minor == 5 and timezone.now() > timezone.datetime(year=2025, month=6, day=24, tzinfo=timezone.utc):
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A016"))
elif mariadb_version.major == 10 and mariadb_version.minor in [0, 1, 2, 3, 4, 7, 9, 10]: # Demote versions down here once EOL
errors.append(Error(f"MariaDB {mariadb_version.public} EOL", hint="https://mariadb.org/download/?t=repo-config", id="allianceauth.checks.A017"))
return errors
@register()
def system_package_sqlite(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
for connection in db.connections.all():
if connection.vendor == "sqlite":
try:
sqlite_version = Pep440Version(".".join(str(i) for i in sqlite_version_info))
except InvalidVersion:
errors.append(Warning("Unable to confirm SQLite Version"))
return errors
if sqlite_version.major == 3 and sqlite_version.minor < 27:
errors.append(Error(f"SQLite {sqlite_version.public} Unsupported by Django", hint="https://pkgs.org/download/sqlite3", id="allianceauth.checks.A020"))
return errors
@register()
def sql_settings(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
for connection in db.connections.all():
if connection.vendor == "mysql":
if connection.settings_dict["OPTIONS"]["charset"] != "utf8mb4":
errors.append(Error("SQL Charset is not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/89be2456fb2d741b86417e889da9b6129525bec8", id="allianceauth.checks.B001"))
# This hasn't actually been set on AA yet
# if connection.settings_dict["OPTIONS"]["charset"] != "utf8mb4_unicode_ci":
# errors.append(Error("SQL Collation is not set correctly", hint="", id="allianceauth.checks.B002"))
# if connection.vendor == "sqlite":
return errors
@register()
def celery_settings(app_configs, **kwargs) -> List[CheckMessage]:
errors: List[CheckMessage] = []
if current_app.conf.broker_transport_options != {'priority_steps': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'queue_order_strategy': 'priority'}:
errors.append(Error("Celery Priorities are not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/8861ec0a61790eca0261f1adc1cc04ca5f243cbc", id="allianceauth.checks.B003"))
if current_app.conf.broker_connection_retry_on_startup != True:
errors.append(Error("Celery broker_connection_retry_on_startup not set correctly", hint="https://gitlab.com/allianceauth/allianceauth/-/commit/380c41400b535447839e5552df2410af35a75280", id="allianceauth.checks.B004"))
return errors
# IDEAS
# Any other celery things weve manually changed over the years
# I'd be happy to add Community App checks, old versions the owners dont want to support etc.
# Check Default Collation on DB
# Check Charset Collation on all tables