blueprints: add Env tag

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-12-24 20:41:51 +01:00
parent fe1e2aa8af
commit 94b9ebb0bb
No known key found for this signature in database
5 changed files with 52 additions and 1 deletions

View File

@ -24,8 +24,11 @@
"!Find sequence", "!Find sequence",
"!KeyOf scalar", "!KeyOf scalar",
"!Context scalar", "!Context scalar",
"!Context sequence",
"!Format sequence", "!Format sequence",
"!Condition sequence" "!Condition sequence",
"!Env sequence",
"!Env scalar"
], ],
"typescript.preferences.importModuleSpecifier": "non-relative", "typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index", "typescript.preferences.importModuleSpecifierEnding": "index",

View File

@ -4,6 +4,16 @@ context:
policy_property: name policy_property: name
policy_property_value: foo-bar-baz-qux policy_property_value: foo-bar-baz-qux
entries: entries:
- model: authentik_sources_oauth.oauthsource
identifiers:
slug: test
attrs:
name: test
provider_type: github
consumer_key: !Env foo
consumer_secret: !Env [bar, baz]
authentication_flow: !Find [authentik_flows.Flow, [slug, default-source-authentication]]
enrollment_flow: !Find [authentik_flows.Flow, [slug, default-source-enrollment]]
- attrs: - attrs:
expression: return True expression: return True
identifiers: identifiers:

View File

@ -1,4 +1,6 @@
"""Test blueprints v1""" """Test blueprints v1"""
from os import environ
from django.test import TransactionTestCase from django.test import TransactionTestCase
from authentik.blueprints.tests import load_yaml_fixture from authentik.blueprints.tests import load_yaml_fixture
@ -9,6 +11,7 @@ from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding
from authentik.lib.generators import generate_id from authentik.lib.generators import generate_id
from authentik.policies.expression.models import ExpressionPolicy from authentik.policies.expression.models import ExpressionPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.sources.oauth.models import OAuthSource
from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage
from authentik.stages.user_login.models import UserLoginStage from authentik.stages.user_login.models import UserLoginStage
@ -132,6 +135,7 @@ class TestBlueprintsV1(TransactionTestCase):
"""Test some yaml tags""" """Test some yaml tags"""
ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete() ExpressionPolicy.objects.filter(name="foo-bar-baz-qux").delete()
Group.objects.filter(name="test").delete() Group.objects.filter(name="test").delete()
environ["foo"] = generate_id()
importer = Importer(load_yaml_fixture("fixtures/tags.yaml"), {"bar": "baz"}) importer = Importer(load_yaml_fixture("fixtures/tags.yaml"), {"bar": "baz"})
self.assertTrue(importer.validate()[0]) self.assertTrue(importer.validate()[0])
self.assertTrue(importer.apply()) self.assertTrue(importer.apply())
@ -152,6 +156,12 @@ class TestBlueprintsV1(TransactionTestCase):
} }
) )
) )
self.assertTrue(
OAuthSource.objects.filter(
slug="test",
consumer_key=environ["foo"],
)
)
def test_export_validate_import_policies(self): def test_export_validate_import_policies(self):
"""Test export and validate it""" """Test export and validate it"""

View File

@ -4,6 +4,7 @@ from dataclasses import asdict, dataclass, field, is_dataclass
from enum import Enum from enum import Enum
from functools import reduce from functools import reduce
from operator import ixor from operator import ixor
from os import getenv
from typing import Any, Literal, Optional from typing import Any, Literal, Optional
from uuid import UUID from uuid import UUID
@ -160,6 +161,26 @@ class KeyOf(YAMLTag):
) )
class Env(YAMLTag):
"""Lookup environment variable with optional default"""
key: str
default: Optional[Any]
# pylint: disable=unused-argument
def __init__(self, loader: "BlueprintLoader", node: ScalarNode | SequenceNode) -> None:
super().__init__()
self.default = None
if isinstance(node, ScalarNode):
self.key = node.value
if isinstance(node, SequenceNode):
self.key = node.value[0].value
self.default = node.value[1].value
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
return getenv(self.key, self.default)
class Context(YAMLTag): class Context(YAMLTag):
"""Lookup key from instance context""" """Lookup key from instance context"""
@ -332,6 +353,7 @@ class BlueprintLoader(SafeLoader):
self.add_constructor("!Context", Context) self.add_constructor("!Context", Context)
self.add_constructor("!Format", Format) self.add_constructor("!Format", Format)
self.add_constructor("!Condition", Condition) self.add_constructor("!Condition", Condition)
self.add_constructor("!Env", Env)
class EntryInvalidError(SentryIgnoredException): class EntryInvalidError(SentryIgnoredException):

View File

@ -8,6 +8,12 @@ Resolves to the primary key of the model instance defined by id _my-policy-id_.
If no matching entry can be found, an error is raised and the blueprint is invalid. If no matching entry can be found, an error is raised and the blueprint is invalid.
#### `!Env`
Example: `password: !Env my_env_var`
Returns the value of the given environment variable. Can be used as a scalar with `!Env my_env_var, default` to return a default value.
#### `!Find` #### `!Find`
Examples: Examples: