ATH-01-001: resolve path and check start before loading blueprints

This is even less of an issue since 411ef239f6, since with that commit we only allow files that the listing returns

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-06-01 13:12:02 +02:00
parent be85eecac5
commit bd54d034e1
No known key found for this signature in database
3 changed files with 44 additions and 27 deletions

View File

@ -82,7 +82,9 @@ class BlueprintInstance(SerializerModel, ManagedModel, CreatedUpdatedModel):
def retrieve_file(self) -> str: def retrieve_file(self) -> str:
"""Get blueprint from path""" """Get blueprint from path"""
try: try:
full_path = Path(CONFIG.y("blueprints_dir")).joinpath(Path(self.path)) full_path = Path(CONFIG.y("blueprints_dir")).joinpath(Path(self.path)).resolve()
if not str(full_path).startswith(CONFIG.y("blueprints_dir")):
raise BlueprintRetrievalFailed("Invalid blueprint path")
with full_path.open("r", encoding="utf-8") as _file: with full_path.open("r", encoding="utf-8") as _file:
return _file.read() return _file.read()
except (IOError, OSError) as exc: except (IOError, OSError) as exc:

View File

@ -1,34 +1,15 @@
"""authentik managed models tests""" """authentik managed models tests"""
from typing import Callable, Type
from django.apps import apps
from django.test import TestCase from django.test import TestCase
from authentik.blueprints.v1.importer import is_model_allowed from authentik.blueprints.models import BlueprintInstance, BlueprintRetrievalFailed
from authentik.lib.models import SerializerModel from authentik.lib.generators import generate_id
class TestModels(TestCase): class TestModels(TestCase):
"""Test Models""" """Test Models"""
def test_retrieve_file(self):
def serializer_tester_factory(test_model: Type[SerializerModel]) -> Callable: """Test retrieve_file"""
"""Test serializer""" instance = BlueprintInstance.objects.create(name=generate_id(), path="../etc/hosts")
with self.assertRaises(BlueprintRetrievalFailed):
def tester(self: TestModels): instance.retrieve()
if test_model._meta.abstract: # pragma: no cover
return
model_class = test_model()
self.assertTrue(isinstance(model_class, SerializerModel))
self.assertIsNotNone(model_class.serializer)
return tester
for app in apps.get_app_configs():
if not app.label.startswith("authentik"):
continue
for model in app.get_models():
if not is_model_allowed(model):
continue
setattr(TestModels, f"test_{app.label}_{model.__name__}", serializer_tester_factory(model))

View File

@ -0,0 +1,34 @@
"""authentik managed models tests"""
from typing import Callable, Type
from django.apps import apps
from django.test import TestCase
from authentik.blueprints.v1.importer import is_model_allowed
from authentik.lib.models import SerializerModel
class TestModels(TestCase):
"""Test Models"""
def serializer_tester_factory(test_model: Type[SerializerModel]) -> Callable:
"""Test serializer"""
def tester(self: TestModels):
if test_model._meta.abstract: # pragma: no cover
return
model_class = test_model()
self.assertTrue(isinstance(model_class, SerializerModel))
self.assertIsNotNone(model_class.serializer)
return tester
for app in apps.get_app_configs():
if not app.label.startswith("authentik"):
continue
for model in app.get_models():
if not is_model_allowed(model):
continue
setattr(TestModels, f"test_{app.label}_{model.__name__}", serializer_tester_factory(model))