diff --git a/authentik/__init__.py b/authentik/__init__.py index 8ead9104c..3d5ec3d73 100644 --- a/authentik/__init__.py +++ b/authentik/__init__.py @@ -1,3 +1,19 @@ """authentik""" +from os import environ +from typing import Optional + __version__ = "2021.12.5" ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" + + +def get_build_hash(fallback: Optional[str] = None) -> str: + """Get build hash""" + return environ.get(ENV_GIT_HASH_KEY, fallback if fallback else "") + + +def get_full_version() -> str: + """Get full version, with build hash appended""" + version = __version__ + if (build_hash := get_build_hash()) != "": + version += "." + build_hash + return version diff --git a/authentik/admin/api/version.py b/authentik/admin/api/version.py index 8ea95e094..e0cc2c5b4 100644 --- a/authentik/admin/api/version.py +++ b/authentik/admin/api/version.py @@ -1,6 +1,4 @@ """authentik administration overview""" -from os import environ - from django.core.cache import cache from drf_spectacular.utils import extend_schema from packaging.version import parse @@ -10,7 +8,7 @@ from rest_framework.request import Request from rest_framework.response import Response from rest_framework.views import APIView -from authentik import ENV_GIT_HASH_KEY, __version__ +from authentik import __version__, get_build_hash from authentik.admin.tasks import VERSION_CACHE_KEY, update_latest_version from authentik.core.api.utils import PassiveSerializer @@ -25,7 +23,7 @@ class VersionSerializer(PassiveSerializer): def get_build_hash(self, _) -> str: """Get build hash, if version is not latest or released""" - return environ.get(ENV_GIT_HASH_KEY, "") + return get_build_hash() def get_version_current(self, _) -> str: """Get current version""" diff --git a/authentik/admin/tasks.py b/authentik/admin/tasks.py index 2c7e91810..ce3d5aaaf 100644 --- a/authentik/admin/tasks.py +++ b/authentik/admin/tasks.py @@ -1,6 +1,5 @@ """authentik admin tasks""" import re -from os import environ from django.core.cache import cache from django.core.validators import URLValidator @@ -9,7 +8,7 @@ from prometheus_client import Info from requests import RequestException from structlog.stdlib import get_logger -from authentik import ENV_GIT_HASH_KEY, __version__ +from authentik import __version__, get_build_hash from authentik.events.models import Event, EventAction, Notification from authentik.events.monitored_tasks import ( MonitoredTask, @@ -36,7 +35,7 @@ def _set_prom_info(): { "version": __version__, "latest": cache.get(VERSION_CACHE_KEY, ""), - "build_hash": environ.get(ENV_GIT_HASH_KEY, ""), + "build_hash": get_build_hash(), } ) diff --git a/authentik/lib/utils/http.py b/authentik/lib/utils/http.py index a6ea7cfab..6ef90e835 100644 --- a/authentik/lib/utils/http.py +++ b/authentik/lib/utils/http.py @@ -1,5 +1,4 @@ """http helpers""" -from os import environ from typing import Any, Optional from django.http import HttpRequest @@ -7,7 +6,7 @@ from requests.sessions import Session from sentry_sdk.hub import Hub from structlog.stdlib import get_logger -from authentik import ENV_GIT_HASH_KEY, __version__ +from authentik import get_full_version OUTPOST_REMOTE_IP_HEADER = "HTTP_X_AUTHENTIK_REMOTE_IP" OUTPOST_TOKEN_HEADER = "HTTP_X_AUTHENTIK_OUTPOST_TOKEN" # nosec @@ -75,8 +74,7 @@ def get_client_ip(request: Optional[HttpRequest]) -> str: def authentik_user_agent() -> str: """Get a common user agent""" - build = environ.get(ENV_GIT_HASH_KEY, "tagged") - return f"authentik@{__version__} (build={build})" + return f"authentik@{get_full_version()}" def get_http_session() -> Session: diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py index 7ba2b7563..9df29d117 100644 --- a/authentik/outposts/api/outposts.py +++ b/authentik/outposts/api/outposts.py @@ -1,6 +1,4 @@ """Outpost API Views""" -from os import environ - from dacite.core import from_dict from dacite.exceptions import DaciteError from django_filters.filters import ModelMultipleChoiceFilter @@ -14,7 +12,7 @@ from rest_framework.response import Response from rest_framework.serializers import JSONField, ModelSerializer, ValidationError from rest_framework.viewsets import ModelViewSet -from authentik import ENV_GIT_HASH_KEY +from authentik import get_build_hash from authentik.core.api.providers import ProviderSerializer from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer, is_dict @@ -154,7 +152,7 @@ class OutpostViewSet(UsedByMixin, ModelViewSet): "version_should": state.version_should, "version_outdated": state.version_outdated, "build_hash": state.build_hash, - "build_hash_should": environ.get(ENV_GIT_HASH_KEY, ""), + "build_hash_should": get_build_hash(), } ) return Response(OutpostHealthSerializer(states, many=True).data) diff --git a/authentik/outposts/controllers/base.py b/authentik/outposts/controllers/base.py index 383a11964..a4ede702a 100644 --- a/authentik/outposts/controllers/base.py +++ b/authentik/outposts/controllers/base.py @@ -1,12 +1,11 @@ """Base Controller""" from dataclasses import dataclass -from os import environ from typing import Optional from structlog.stdlib import get_logger from structlog.testing import capture_logs -from authentik import ENV_GIT_HASH_KEY, __version__ +from authentik import __version__, get_build_hash from authentik.lib.config import CONFIG from authentik.lib.sentry import SentryIgnoredException from authentik.outposts.models import ( @@ -102,5 +101,5 @@ class BaseController: return image_name_template % { "type": self.outpost.type, "version": __version__, - "build_hash": environ.get(ENV_GIT_HASH_KEY, ""), + "build_hash": get_build_hash(), } diff --git a/authentik/outposts/models.py b/authentik/outposts/models.py index f0fe98497..9c3efe8e0 100644 --- a/authentik/outposts/models.py +++ b/authentik/outposts/models.py @@ -1,7 +1,6 @@ """Outpost models""" from dataclasses import asdict, dataclass, field from datetime import datetime -from os import environ from typing import Iterable, Optional from uuid import uuid4 @@ -17,7 +16,7 @@ from model_utils.managers import InheritanceManager from packaging.version import LegacyVersion, Version, parse from structlog.stdlib import get_logger -from authentik import ENV_GIT_HASH_KEY, __version__ +from authentik import __version__, get_build_hash from authentik.core.models import ( USER_ATTRIBUTE_CAN_OVERRIDE_IP, USER_ATTRIBUTE_SA, @@ -414,7 +413,7 @@ class OutpostState: """Check if outpost version matches our version""" if not self.version: return False - if self.build_hash != environ.get(ENV_GIT_HASH_KEY, ""): + if self.build_hash != get_build_hash(): return False return parse(self.version) < OUR_VERSION diff --git a/authentik/root/settings.py b/authentik/root/settings.py index bd21a34e1..acdad9a6c 100644 --- a/authentik/root/settings.py +++ b/authentik/root/settings.py @@ -30,7 +30,7 @@ from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.redis import RedisIntegration from sentry_sdk.integrations.threading import ThreadingIntegration -from authentik import ENV_GIT_HASH_KEY, __version__ +from authentik import ENV_GIT_HASH_KEY, __version__, get_build_hash, get_full_version from authentik.core.middleware import structlog_add_request_id from authentik.lib.config import CONFIG from authentik.lib.logging import add_process_id @@ -396,10 +396,6 @@ if CONFIG.y("postgresql.s3_backup.bucket", "") != "": # Sentry integration SENTRY_DSN = "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8" -# Default to empty string as that is what docker has -build_hash = os.environ.get(ENV_GIT_HASH_KEY, "") -if build_hash == "": - build_hash = "tagged" env = get_env() _ERROR_REPORTING = CONFIG.y_bool("error_reporting.enabled", False) @@ -420,7 +416,7 @@ if _ERROR_REPORTING: environment=CONFIG.y("error_reporting.environment", "customer"), send_default_pii=CONFIG.y_bool("error_reporting.send_pii", False), ) - set_tag("authentik.build_hash", build_hash) + set_tag("authentik.build_hash", get_build_hash("tagged")) set_tag("authentik.env", env) set_tag("authentik.component", "backend") set_tag("authentik.uuid", sha512(SECRET_KEY.encode("ascii")).hexdigest()[:16]) @@ -437,10 +433,9 @@ if not CONFIG.y_bool("disable_startup_analytics", False): json={ "domain": "authentik", "name": "pageview", - "referrer": f"{__version__} ({build_hash})", + "referrer": get_full_version(), "url": ( - f"http://localhost/{env}?utm_source={__version__}-" - f"{build_hash}&utm_medium={env}" + f"http://localhost/{env}?utm_source={get_full_version()}&utm_medium={env}" ), }, headers={