blueprints: don't use example label, add more tags and tests for tags
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
201bea6d30
commit
872c18dddc
|
@ -82,8 +82,7 @@ COPY ./pyproject.toml /
|
||||||
COPY ./xml /xml
|
COPY ./xml /xml
|
||||||
COPY ./tests /tests
|
COPY ./tests /tests
|
||||||
COPY ./manage.py /
|
COPY ./manage.py /
|
||||||
COPY ./blueprints/default /blueprints/default
|
COPY ./blueprints /blueprints
|
||||||
COPY ./blueprints/system /blueprints/system
|
|
||||||
COPY ./lifecycle/ /lifecycle
|
COPY ./lifecycle/ /lifecycle
|
||||||
COPY --from=builder /work/authentik /authentik-proxy
|
COPY --from=builder /work/authentik /authentik-proxy
|
||||||
COPY --from=web-builder /work/web/dist/ /web/dist/
|
COPY --from=web-builder /work/web/dist/ /web/dist/
|
||||||
|
|
|
@ -19,10 +19,12 @@ def check_blueprint_v1_file(BlueprintInstance: type["BlueprintInstance"], path:
|
||||||
"""Check if blueprint should be imported"""
|
"""Check if blueprint should be imported"""
|
||||||
from authentik.blueprints.models import BlueprintInstanceStatus
|
from authentik.blueprints.models import BlueprintInstanceStatus
|
||||||
from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata
|
from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata
|
||||||
from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_EXAMPLE
|
from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_INSTANTIATE
|
||||||
|
|
||||||
with open(path, "r", encoding="utf-8") as blueprint_file:
|
with open(path, "r", encoding="utf-8") as blueprint_file:
|
||||||
raw_blueprint = load(blueprint_file.read(), BlueprintLoader)
|
raw_blueprint = load(blueprint_file.read(), BlueprintLoader)
|
||||||
|
if not raw_blueprint:
|
||||||
|
return
|
||||||
metadata = raw_blueprint.get("metadata", None)
|
metadata = raw_blueprint.get("metadata", None)
|
||||||
version = raw_blueprint.get("version", 1)
|
version = raw_blueprint.get("version", 1)
|
||||||
if version != 1:
|
if version != 1:
|
||||||
|
@ -33,7 +35,7 @@ def check_blueprint_v1_file(BlueprintInstance: type["BlueprintInstance"], path:
|
||||||
meta = None
|
meta = None
|
||||||
if metadata:
|
if metadata:
|
||||||
meta = from_dict(BlueprintMetadata, metadata)
|
meta = from_dict(BlueprintMetadata, metadata)
|
||||||
if meta.labels.get(LABEL_AUTHENTIK_EXAMPLE, "").lower() == "true":
|
if meta.labels.get(LABEL_AUTHENTIK_INSTANTIATE, "").lower() == "false":
|
||||||
return
|
return
|
||||||
if not instance:
|
if not instance:
|
||||||
instance = BlueprintInstance(
|
instance = BlueprintInstance(
|
||||||
|
|
|
@ -24,6 +24,18 @@ entries:
|
||||||
order: 0
|
order: 0
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
YAML_TAG_TESTS = """version: 1
|
||||||
|
context:
|
||||||
|
foo: bar
|
||||||
|
entries:
|
||||||
|
- attrs:
|
||||||
|
expression: return True
|
||||||
|
identifiers:
|
||||||
|
name: !Format [foo-%s-%s, !Context foo, !Context bar]
|
||||||
|
id: default-source-enrollment-if-username
|
||||||
|
model: authentik_policies_expression.expressionpolicy
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class TestBlueprintsV1(TransactionTestCase):
|
class TestBlueprintsV1(TransactionTestCase):
|
||||||
"""Test Blueprints"""
|
"""Test Blueprints"""
|
||||||
|
@ -85,6 +97,14 @@ class TestBlueprintsV1(TransactionTestCase):
|
||||||
|
|
||||||
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before)
|
self.assertEqual(Prompt.objects.filter(field_key="username").count(), count_before)
|
||||||
|
|
||||||
|
def test_import_yaml_tags(self):
|
||||||
|
"""Test some yaml tags"""
|
||||||
|
ExpressionPolicy.objects.filter(name="foo-foo-bar").delete()
|
||||||
|
importer = Importer(YAML_TAG_TESTS, {"bar": "baz"})
|
||||||
|
self.assertTrue(importer.validate()[0])
|
||||||
|
self.assertTrue(importer.apply())
|
||||||
|
self.assertTrue(ExpressionPolicy.objects.filter(name="foo-foo-bar"))
|
||||||
|
|
||||||
def test_export_validate_import_policies(self):
|
def test_export_validate_import_policies(self):
|
||||||
"""Test export and validate it"""
|
"""Test export and validate it"""
|
||||||
flow_slug = generate_id()
|
flow_slug = generate_id()
|
||||||
|
|
|
@ -160,6 +160,29 @@ class Context(YAMLTag):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class Format(YAMLTag):
|
||||||
|
"""Format a string"""
|
||||||
|
|
||||||
|
format_string: str
|
||||||
|
args: list[Any]
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
def __init__(self, loader: "BlueprintLoader", node: SequenceNode) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.format_string = node.value[0].value
|
||||||
|
self.args = []
|
||||||
|
for raw_node in node.value[1:]:
|
||||||
|
self.args.append(raw_node.value)
|
||||||
|
|
||||||
|
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
|
||||||
|
try:
|
||||||
|
print(self.format_string)
|
||||||
|
print(self.args)
|
||||||
|
return self.format_string % tuple(self.args)
|
||||||
|
except TypeError as exc:
|
||||||
|
raise EntryInvalidError(exc)
|
||||||
|
|
||||||
|
|
||||||
class Find(YAMLTag):
|
class Find(YAMLTag):
|
||||||
"""Find any object"""
|
"""Find any object"""
|
||||||
|
|
||||||
|
@ -214,6 +237,7 @@ class BlueprintLoader(SafeLoader):
|
||||||
self.add_constructor("!KeyOf", KeyOf)
|
self.add_constructor("!KeyOf", KeyOf)
|
||||||
self.add_constructor("!Find", Find)
|
self.add_constructor("!Find", Find)
|
||||||
self.add_constructor("!Context", Context)
|
self.add_constructor("!Context", Context)
|
||||||
|
self.add_constructor("!Format", Format)
|
||||||
|
|
||||||
|
|
||||||
class EntryInvalidError(SentryIgnoredException):
|
class EntryInvalidError(SentryIgnoredException):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
"""Blueprint labels"""
|
"""Blueprint labels"""
|
||||||
|
|
||||||
LABEL_AUTHENTIK_SYSTEM = "blueprints.goauthentik.io/system"
|
LABEL_AUTHENTIK_SYSTEM = "blueprints.goauthentik.io/system"
|
||||||
LABEL_AUTHENTIK_EXAMPLE = "blueprints.goauthentik.io/example"
|
LABEL_AUTHENTIK_INSTANTIATE = "blueprints.goauthentik.io/instantiate"
|
||||||
|
|
|
@ -14,7 +14,7 @@ from yaml.error import YAMLError
|
||||||
from authentik.blueprints.models import BlueprintInstance, BlueprintInstanceStatus
|
from authentik.blueprints.models import BlueprintInstance, BlueprintInstanceStatus
|
||||||
from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata
|
from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata
|
||||||
from authentik.blueprints.v1.importer import Importer
|
from authentik.blueprints.v1.importer import Importer
|
||||||
from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_EXAMPLE
|
from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_INSTANTIATE
|
||||||
from authentik.events.monitored_tasks import (
|
from authentik.events.monitored_tasks import (
|
||||||
MonitoredTask,
|
MonitoredTask,
|
||||||
TaskResult,
|
TaskResult,
|
||||||
|
@ -59,11 +59,6 @@ def blueprints_find():
|
||||||
file_hash = sha512(path.read_bytes()).hexdigest()
|
file_hash = sha512(path.read_bytes()).hexdigest()
|
||||||
blueprint = BlueprintFile(path.relative_to(root), version, file_hash, path.stat().st_mtime)
|
blueprint = BlueprintFile(path.relative_to(root), version, file_hash, path.stat().st_mtime)
|
||||||
blueprint.meta = from_dict(BlueprintMetadata, metadata) if metadata else None
|
blueprint.meta = from_dict(BlueprintMetadata, metadata) if metadata else None
|
||||||
if (
|
|
||||||
blueprint.meta
|
|
||||||
and blueprint.meta.labels.get(LABEL_AUTHENTIK_EXAMPLE, "").lower() == "true"
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
blueprints.append(blueprint)
|
blueprints.append(blueprint)
|
||||||
return blueprints
|
return blueprints
|
||||||
|
|
||||||
|
@ -89,6 +84,11 @@ def blueprints_discover(self: MonitoredTask):
|
||||||
def check_blueprint_v1_file(blueprint: BlueprintFile):
|
def check_blueprint_v1_file(blueprint: BlueprintFile):
|
||||||
"""Check if blueprint should be imported"""
|
"""Check if blueprint should be imported"""
|
||||||
instance: BlueprintInstance = BlueprintInstance.objects.filter(path=blueprint.path).first()
|
instance: BlueprintInstance = BlueprintInstance.objects.filter(path=blueprint.path).first()
|
||||||
|
if (
|
||||||
|
blueprint.meta
|
||||||
|
and blueprint.meta.labels.get(LABEL_AUTHENTIK_INSTANTIATE, "").lower() == "false"
|
||||||
|
):
|
||||||
|
return
|
||||||
if not instance:
|
if not instance:
|
||||||
instance = BlueprintInstance(
|
instance = BlueprintInstance(
|
||||||
name=blueprint.meta.name if blueprint.meta else str(blueprint.path),
|
name=blueprint.meta.name if blueprint.meta else str(blueprint.path),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: 1
|
version: 1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
blueprints.goauthentik.io/example: "true"
|
blueprints.goauthentik.io/instantiate: "false"
|
||||||
name: Example - Enrollment (2 Stage)
|
name: Example - Enrollment (2 Stage)
|
||||||
entries:
|
entries:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: 1
|
version: 1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
blueprints.goauthentik.io/example: "true"
|
blueprints.goauthentik.io/instantiate: "false"
|
||||||
name: Example - Enrollment with email verification
|
name: Example - Enrollment with email verification
|
||||||
entries:
|
entries:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: 1
|
version: 1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
blueprints.goauthentik.io/example: "true"
|
blueprints.goauthentik.io/instantiate: "false"
|
||||||
name: Example - Two-factor Login
|
name: Example - Two-factor Login
|
||||||
entries:
|
entries:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: 1
|
version: 1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
blueprints.goauthentik.io/example: "true"
|
blueprints.goauthentik.io/instantiate: "false"
|
||||||
name: Example - Login with conditional Captcha
|
name: Example - Login with conditional Captcha
|
||||||
entries:
|
entries:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: 1
|
version: 1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
blueprints.goauthentik.io/example: "true"
|
blueprints.goauthentik.io/instantiate: "false"
|
||||||
name: Example - Recovery with email verification
|
name: Example - Recovery with email verification
|
||||||
entries:
|
entries:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
version: 1
|
version: 1
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
blueprints.goauthentik.io/example: "true"
|
blueprints.goauthentik.io/instantiate: "false"
|
||||||
name: Example - User deletion
|
name: Example - User deletion
|
||||||
entries:
|
entries:
|
||||||
- identifiers:
|
- identifiers:
|
||||||
|
|
Reference in a new issue