blueprints: allow setting of token key in blueprint context (#4995)
closes #4717 Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
1d5f399b61
commit
4d8d405e70
|
@ -19,10 +19,8 @@ class Command(BaseCommand):
|
|||
for blueprint_path in options.get("blueprints", []):
|
||||
content = BlueprintInstance(path=blueprint_path).retrieve()
|
||||
importer = Importer(content)
|
||||
valid, logs = importer.validate()
|
||||
valid, _ = importer.validate()
|
||||
if not valid:
|
||||
for log in logs:
|
||||
getattr(LOGGER, log.pop("log_level"))(**log)
|
||||
self.stderr.write("blueprint invalid")
|
||||
sys_exit(1)
|
||||
importer.apply()
|
||||
|
|
|
@ -40,6 +40,10 @@ from authentik.lib.models import SerializerModel
|
|||
from authentik.outposts.models import OutpostServiceConnection
|
||||
from authentik.policies.models import Policy, PolicyBindingModel
|
||||
|
||||
# Context set when the serializer is created in a blueprint context
|
||||
# Update website/developer-docs/blueprints/v1/models.md when used
|
||||
SERIALIZER_CONTEXT_BLUEPRINT = "blueprint_entry"
|
||||
|
||||
|
||||
def is_model_allowed(model: type[Model]) -> bool:
|
||||
"""Check if model is allowed"""
|
||||
|
@ -158,7 +162,12 @@ class Importer:
|
|||
raise EntryInvalidError(f"Model {model} not allowed")
|
||||
if issubclass(model, BaseMetaModel):
|
||||
serializer_class: type[Serializer] = model.serializer()
|
||||
serializer = serializer_class(data=entry.get_attrs(self.__import))
|
||||
serializer = serializer_class(
|
||||
data=entry.get_attrs(self.__import),
|
||||
context={
|
||||
SERIALIZER_CONTEXT_BLUEPRINT: entry,
|
||||
},
|
||||
)
|
||||
try:
|
||||
serializer.is_valid(raise_exception=True)
|
||||
except ValidationError as exc:
|
||||
|
@ -217,7 +226,12 @@ class Importer:
|
|||
always_merger.merge(full_data, updated_identifiers)
|
||||
serializer_kwargs["data"] = full_data
|
||||
|
||||
serializer: Serializer = model().serializer(**serializer_kwargs)
|
||||
serializer: Serializer = model().serializer(
|
||||
context={
|
||||
SERIALIZER_CONTEXT_BLUEPRINT: entry,
|
||||
},
|
||||
**serializer_kwargs,
|
||||
)
|
||||
try:
|
||||
serializer.is_valid(raise_exception=True)
|
||||
except ValidationError as exc:
|
||||
|
|
|
@ -16,6 +16,7 @@ from rest_framework.viewsets import ModelViewSet
|
|||
from authentik.api.authorization import OwnerSuperuserPermissions
|
||||
from authentik.api.decorators import permission_required
|
||||
from authentik.blueprints.api import ManagedSerializer
|
||||
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.users import UserSerializer
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
|
@ -29,6 +30,11 @@ class TokenSerializer(ManagedSerializer, ModelSerializer):
|
|||
|
||||
user_obj = UserSerializer(required=False, source="user", read_only=True)
|
||||
|
||||
def __init__(self, *args, **kwargs) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
if SERIALIZER_CONTEXT_BLUEPRINT in self.context:
|
||||
self.fields["key"] = CharField()
|
||||
|
||||
def validate(self, attrs: dict[Any, str]) -> dict[Any, str]:
|
||||
"""Ensure only API or App password tokens are created."""
|
||||
request: Request = self.context.get("request")
|
||||
|
|
|
@ -18,7 +18,7 @@ When authenticating with a flow, you'll get an authenticated Session cookie, tha
|
|||
|
||||
### API Token
|
||||
|
||||
Superusers can create tokens to authenticate as any user with a static key, which can optionally be expiring and auto-rotate.
|
||||
Users can create tokens to authenticate as any user with a static key, which can optionally be expiring and auto-rotate.
|
||||
|
||||
### JWT Token
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Models
|
||||
|
||||
Some models behave differently and allow for access to different API fields when created via blueprint.
|
||||
|
||||
### `authentik_core.token`
|
||||
|
||||
:::info
|
||||
Requires authentik 2023.4
|
||||
:::
|
||||
|
||||
Via the standard API, a token's key cannot be changed, it can only be rotated. This is to ensure a high entropy in it's key, and to prevent insecure data from being used. However, when provisioning tokens via a blueprint, it may be required to set a token to an existing value.
|
||||
|
||||
With blueprints, the field `key` can be set, to set the token's key to any value.
|
||||
|
||||
For example:
|
||||
|
||||
```yaml
|
||||
# [...]
|
||||
- model: authentik_core.token
|
||||
state: present
|
||||
identifiers:
|
||||
identifier: my-token
|
||||
attrs:
|
||||
key: this-should-be-a-long-value
|
||||
user: !KeyOf my-user
|
||||
intent: api
|
||||
```
|
|
@ -16,6 +16,7 @@ module.exports = {
|
|||
"blueprints/v1/structure",
|
||||
"blueprints/v1/tags",
|
||||
"blueprints/v1/example",
|
||||
"blueprints/v1/models",
|
||||
"blueprints/v1/meta",
|
||||
],
|
||||
},
|
||||
|
|
Reference in New Issue