diff --git a/authentik/api/v2/urls.py b/authentik/api/v2/urls.py index 34eb63470..71e27a9cf 100644 --- a/authentik/api/v2/urls.py +++ b/authentik/api/v2/urls.py @@ -29,11 +29,12 @@ from authentik.flows.api import ( FlowViewSet, StageViewSet, ) -from authentik.outposts.api import ( +from authentik.outposts.api.outpost_service_connections import ( DockerServiceConnectionViewSet, KubernetesServiceConnectionViewSet, - OutpostViewSet, + ServiceConnectionViewSet, ) +from authentik.outposts.api.outposts import OutpostViewSet from authentik.policies.api import ( PolicyBindingViewSet, PolicyCacheViewSet, @@ -88,6 +89,7 @@ router.register("core/users", UserViewSet) router.register("core/tokens", TokenViewSet) router.register("outposts/outposts", OutpostViewSet) +router.register("outposts/service_connections/all", ServiceConnectionViewSet) router.register("outposts/service_connections/docker", DockerServiceConnectionViewSet) router.register( "outposts/service_connections/kubernetes", KubernetesServiceConnectionViewSet diff --git a/authentik/outposts/api/__init__.py b/authentik/outposts/api/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/authentik/outposts/api.py b/authentik/outposts/api/outpost_service_connections.py similarity index 73% rename from authentik/outposts/api.py rename to authentik/outposts/api/outpost_service_connections.py index d6815a955..46f142ae6 100644 --- a/authentik/outposts/api.py +++ b/authentik/outposts/api/outpost_service_connections.py @@ -1,30 +1,28 @@ """Outpost API Views""" -from rest_framework.serializers import JSONField, ModelSerializer +from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.outposts.models import ( DockerServiceConnection, KubernetesServiceConnection, - Outpost, + OutpostServiceConnection, ) -class OutpostSerializer(ModelSerializer): - """Outpost Serializer""" - - _config = JSONField() +class ServiceConnectionSerializer(ModelSerializer): + """ServiceConnection Serializer""" class Meta: - model = Outpost - fields = ["pk", "name", "providers", "service_connection", "_config"] + model = OutpostServiceConnection + fields = ["pk", "name"] -class OutpostViewSet(ModelViewSet): - """Outpost Viewset""" +class ServiceConnectionViewSet(ModelViewSet): + """ServiceConnection Viewset""" - queryset = Outpost.objects.all() - serializer_class = OutpostSerializer + queryset = OutpostServiceConnection.objects.all() + serializer_class = ServiceConnectionSerializer class DockerServiceConnectionSerializer(ModelSerializer): diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py new file mode 100644 index 000000000..c3c054620 --- /dev/null +++ b/authentik/outposts/api/outposts.py @@ -0,0 +1,71 @@ +"""Outpost API Views""" +from django.db.models import Model +from drf_yasg2.utils import swagger_auto_schema +from rest_framework.decorators import action +from rest_framework.fields import BooleanField, CharField, DateTimeField +from rest_framework.request import Request +from rest_framework.response import Response +from rest_framework.serializers import JSONField, ModelSerializer, Serializer +from rest_framework.viewsets import ModelViewSet + +from authentik.core.api.providers import ProviderSerializer +from authentik.outposts.models import Outpost + + +class OutpostSerializer(ModelSerializer): + """Outpost Serializer""" + + _config = JSONField() + providers = ProviderSerializer(many=True, read_only=True) + + class Meta: + + model = Outpost + fields = [ + "pk", + "name", + "providers", + "service_connection", + "token_identifier", + "_config", + ] + + +class OutpostHealthSerializer(Serializer): + """Outpost health status""" + + last_seen = DateTimeField(read_only=True) + version = CharField(read_only=True) + version_should = CharField(read_only=True) + version_outdated = BooleanField(read_only=True) + + def create(self, validated_data: dict) -> Model: + raise NotImplementedError + + def update(self, instance: Model, validated_data: dict) -> Model: + raise NotImplementedError + + +class OutpostViewSet(ModelViewSet): + """Outpost Viewset""" + + queryset = Outpost.objects.all() + serializer_class = OutpostSerializer + + @swagger_auto_schema(responses={200: OutpostHealthSerializer(many=True)}) + @action(methods=["GET"], detail=True) + # pylint: disable=invalid-name, unused-argument + def health(self, request: Request, pk: int) -> Response: + """Get outposts current health""" + outpost: Outpost = self.get_object() + states = [] + for state in outpost.state: + states.append( + { + "last_seen": state.last_seen, + "version": state.version, + "version_should": state.version_should, + "version_outdated": state.version_outdated, + } + ) + return Response(OutpostHealthSerializer(states, many=True).data) diff --git a/authentik/outposts/models.py b/authentik/outposts/models.py index be9a359fb..eb2056dff 100644 --- a/authentik/outposts/models.py +++ b/authentik/outposts/models.py @@ -9,7 +9,6 @@ from django.core.cache import cache from django.db import models, transaction from django.db.models.base import Model from django.forms.models import ModelForm -from django.http import HttpRequest from django.utils.translation import gettext_lazy as _ from docker.client import DockerClient from docker.errors import DockerException @@ -33,7 +32,6 @@ from authentik.crypto.models import CertificateKeyPair from authentik.lib.config import CONFIG from authentik.lib.models import InheritanceForeignKey from authentik.lib.sentry import SentryIgnoredException -from authentik.lib.utils.template import render_to_string from authentik.outposts.docker_tls import DockerInlineTLS OUR_VERSION = parse(__version__) @@ -378,13 +376,6 @@ class Outpost(models.Model): objects.append(provider) return objects - def html_deployment_view(self, request: HttpRequest) -> Optional[str]: - """return template and context modal to view token and other config info""" - return render_to_string( - "outposts/deployment_modal.html", - {"outpost": self, "full_url": request.build_absolute_uri("/")}, - ) - def __str__(self) -> str: return f"Outpost {self.name}" diff --git a/authentik/outposts/templates/outposts/deployment_modal.html b/authentik/outposts/templates/outposts/deployment_modal.html deleted file mode 100644 index cbd29db90..000000000 --- a/authentik/outposts/templates/outposts/deployment_modal.html +++ /dev/null @@ -1,43 +0,0 @@ -{% load i18n %} - - - -
-
-

{% trans 'Outpost Deployment Info' %}

-
- - -
-
diff --git a/authentik/providers/oauth2/api.py b/authentik/providers/oauth2/api.py index c58270764..13edd2c66 100644 --- a/authentik/providers/oauth2/api.py +++ b/authentik/providers/oauth2/api.py @@ -59,11 +59,11 @@ class OAuth2ProviderViewSet(ModelViewSet): queryset = OAuth2Provider.objects.all() serializer_class = OAuth2ProviderSerializer - @action(methods=["GET"], detail=True) @swagger_auto_schema(responses={200: OAuth2ProviderSetupURLs(many=False)}) + @action(methods=["GET"], detail=True) # pylint: disable=invalid-name def setup_urls(self, request: Request, pk: int) -> str: - """Return metadata as XML string""" + """Get Providers setup URLs""" provider = get_object_or_404(OAuth2Provider, pk=pk) data = { "issuer": provider.get_issuer(request), diff --git a/authentik/providers/saml/api.py b/authentik/providers/saml/api.py index 11d02bf62..1163afe95 100644 --- a/authentik/providers/saml/api.py +++ b/authentik/providers/saml/api.py @@ -54,10 +54,10 @@ class SAMLProviderViewSet(ModelViewSet): queryset = SAMLProvider.objects.all() serializer_class = SAMLProviderSerializer - @action(methods=["GET"], detail=True) @swagger_auto_schema(responses={200: SAMLMetadataSerializer(many=False)}) + @action(methods=["GET"], detail=True) # pylint: disable=invalid-name - def metadata(self, request: Request, pk: int) -> str: + def metadata(self, request: Request, pk: int) -> Response: """Return metadata as XML string""" provider = get_object_or_404(SAMLProvider, pk=pk) metadata = DescriptorDownloadView.get_metadata(request, provider) diff --git a/swagger.yaml b/swagger.yaml index 799164642..75d42d415 100755 --- a/swagger.yaml +++ b/swagger.yaml @@ -1911,6 +1911,28 @@ paths: required: true type: string format: uuid + /outposts/outposts/{uuid}/health/: + get: + operationId: outposts_outposts_health + description: Outpost Viewset + parameters: [] + responses: + '200': + description: '' + schema: + description: '' + type: array + items: + $ref: '#/definitions/OutpostHealth' + tags: + - outposts + parameters: + - name: uuid + in: path + description: A UUID string identifying this outpost. + required: true + type: string + format: uuid /outposts/proxy/: get: operationId: outposts_proxy_list @@ -2037,6 +2059,133 @@ paths: description: A unique integer value identifying this Proxy Provider. required: true type: integer + /outposts/service_connections/all/: + get: + operationId: outposts_service_connections_all_list + description: ServiceConnection Viewset + parameters: + - name: ordering + in: query + description: Which field to use when ordering the results. + required: false + type: string + - name: search + in: query + description: A search term. + required: false + type: string + - name: page + in: query + description: A page number within the paginated result set. + required: false + type: integer + - name: page_size + in: query + description: Number of results to return per page. + required: false + type: integer + responses: + '200': + description: '' + schema: + required: + - count + - results + type: object + properties: + count: + type: integer + next: + type: string + format: uri + x-nullable: true + previous: + type: string + format: uri + x-nullable: true + results: + type: array + items: + $ref: '#/definitions/ServiceConnection' + tags: + - outposts + post: + operationId: outposts_service_connections_all_create + description: ServiceConnection Viewset + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ServiceConnection' + responses: + '201': + description: '' + schema: + $ref: '#/definitions/ServiceConnection' + tags: + - outposts + parameters: [] + /outposts/service_connections/all/{uuid}/: + get: + operationId: outposts_service_connections_all_read + description: ServiceConnection Viewset + parameters: [] + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ServiceConnection' + tags: + - outposts + put: + operationId: outposts_service_connections_all_update + description: ServiceConnection Viewset + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ServiceConnection' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ServiceConnection' + tags: + - outposts + patch: + operationId: outposts_service_connections_all_partial_update + description: ServiceConnection Viewset + parameters: + - name: data + in: body + required: true + schema: + $ref: '#/definitions/ServiceConnection' + responses: + '200': + description: '' + schema: + $ref: '#/definitions/ServiceConnection' + tags: + - outposts + delete: + operationId: outposts_service_connections_all_delete + description: ServiceConnection Viewset + parameters: [] + responses: + '204': + description: '' + tags: + - outposts + parameters: + - name: uuid + in: path + description: A UUID string identifying this Outpost Service-Connection. + required: true + type: string + format: uuid /outposts/service_connections/docker/: get: operationId: outposts_service_connections_docker_list @@ -8005,7 +8154,6 @@ definitions: description: Outpost Serializer required: - name - - providers - _config type: object properties: @@ -8019,10 +8167,11 @@ definitions: type: string minLength: 1 providers: + description: '' type: array items: - type: integer - uniqueItems: true + $ref: '#/definitions/Provider' + readOnly: true service_connection: title: Service connection description: Select Service-Connection authentik should use to manage this @@ -8033,6 +8182,15 @@ definitions: _config: title: config type: object + OutpostHealth: + description: '' + type: object + properties: + last_seen: + title: Last seen + type: string + format: date-time + readOnly: true OpenIDConnectConfiguration: title: Oidc configuration description: rest_framework Serializer for OIDC Configuration @@ -8170,6 +8328,21 @@ definitions: description: User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used. type: string + ServiceConnection: + description: ServiceConnection Serializer + required: + - name + type: object + properties: + pk: + title: Uuid + type: string + format: uuid + readOnly: true + name: + title: Name + type: string + minLength: 1 DockerServiceConnection: description: DockerServiceConnection Serializer required: