providers/ldap: add search_group to limit who can do search requests

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-04-26 23:25:03 +02:00
parent 2a122845d9
commit 1d5958a78f
6 changed files with 79 additions and 7 deletions

View File

@ -1,5 +1,4 @@
"""User API Views""" """User API Views"""
from authentik.core.api.groups import GroupSerializer
from django.http.response import Http404 from django.http.response import Http404
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.utils.http import urlencode from django.utils.http import urlencode
@ -14,6 +13,7 @@ from rest_framework.viewsets import ModelViewSet
from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h
from authentik.api.decorators import permission_required from authentik.api.decorators import permission_required
from authentik.core.api.groups import GroupSerializer
from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict
from authentik.core.middleware import ( from authentik.core.middleware import (
SESSION_IMPERSONATE_ORIGINAL_USER, SESSION_IMPERSONATE_ORIGINAL_USER,

View File

@ -15,6 +15,7 @@ class LDAPProviderSerializer(ProviderSerializer):
model = LDAPProvider model = LDAPProvider
fields = ProviderSerializer.Meta.fields + [ fields = ProviderSerializer.Meta.fields + [
"base_dn", "base_dn",
"search_group",
] ]
@ -35,7 +36,14 @@ class LDAPOutpostConfigSerializer(ModelSerializer):
class Meta: class Meta:
model = LDAPProvider model = LDAPProvider
fields = ["pk", "name", "base_dn", "bind_flow_slug", "application_slug"] fields = [
"pk",
"name",
"base_dn",
"bind_flow_slug",
"application_slug",
"search_group",
]
class LDAPOutpostConfigViewSet(ReadOnlyModelViewSet): class LDAPOutpostConfigViewSet(ReadOnlyModelViewSet):

View File

@ -0,0 +1,26 @@
# Generated by Django 3.2 on 2021-04-26 19:57
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_core", "0019_source_managed"),
("authentik_providers_ldap", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="ldapprovider",
name="search_group",
field=models.ForeignKey(
default=None,
help_text="Users in this group can do search queries. If not set, every user can execute search queries.",
null=True,
on_delete=django.db.models.deletion.SET_DEFAULT,
to="authentik_core.group",
),
),
]

View File

@ -1,11 +1,11 @@
"""LDAP Provider""" """LDAP Provider"""
from typing import Iterable, Optional, Type from typing import Iterable, Optional, Type, Union
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework.serializers import Serializer from rest_framework.serializers import Serializer
from authentik.core.models import Provider from authentik.core.models import Group, Provider
from authentik.outposts.models import OutpostModel from authentik.outposts.models import OutpostModel
@ -17,6 +17,17 @@ class LDAPProvider(OutpostModel, Provider):
help_text=_("DN under which objects are accessible."), help_text=_("DN under which objects are accessible."),
) )
search_group = models.ForeignKey(
Group,
null=True,
default=None,
on_delete=models.SET_DEFAULT,
help_text=_(
"Users in this group can do search queries. "
"If not set, every user can execute search queries."
),
)
@property @property
def launch_url(self) -> Optional[str]: def launch_url(self) -> Optional[str]:
"""LDAP never has a launch URL""" """LDAP never has a launch URL"""
@ -35,8 +46,8 @@ class LDAPProvider(OutpostModel, Provider):
def __str__(self): def __str__(self):
return f"LDAP Provider {self.name}" return f"LDAP Provider {self.name}"
def get_required_objects(self) -> Iterable[models.Model]: def get_required_objects(self) -> Iterable[Union[models.Model, str]]:
return [self] return [self, "authentik_core.view_user", "authentik_core.view_group"]
class Meta: class Meta:

View File

@ -16051,6 +16051,13 @@ definitions:
title: Application slug title: Application slug
type: string type: string
minLength: 1 minLength: 1
search_group:
title: Search group
description: Users in this group can do search queries. If not set, every
user can execute search queries.
type: string
format: uuid
x-nullable: true
OpenIDConnectConfiguration: OpenIDConnectConfiguration:
description: Embed OpenID Connect provider information description: Embed OpenID Connect provider information
required: required:
@ -17111,6 +17118,13 @@ definitions:
description: DN under which objects are accessible. description: DN under which objects are accessible.
type: string type: string
minLength: 1 minLength: 1
search_group:
title: Search group
description: Users in this group can do search queries. If not set, every
user can execute search queries.
type: string
format: uuid
x-nullable: true
OAuth2ProviderSetupURLs: OAuth2ProviderSetupURLs:
type: object type: object
properties: properties:

View File

@ -1,4 +1,4 @@
import { FlowDesignationEnum, FlowsApi, ProvidersApi, LDAPProvider } from "authentik-api"; import { FlowDesignationEnum, FlowsApi, ProvidersApi, LDAPProvider, CoreApi } from "authentik-api";
import { t } from "@lingui/macro"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
@ -69,6 +69,19 @@ export class LDAPProviderFormPage extends Form<LDAPProvider> {
</select> </select>
<p class="pf-c-form__helper-text">${t`Flow used for users to authenticate. Currently only identification and password stages are supported.`}</p> <p class="pf-c-form__helper-text">${t`Flow used for users to authenticate. Currently only identification and password stages are supported.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal
label=${t`Group`}
name="searchGroup">
<select class="pf-c-form-control">
<option value="" ?selected=${this.provider?.searchGroup === undefined}>---------</option>
${until(new CoreApi(DEFAULT_CONFIG).coreGroupsList({}).then(groups => {
return groups.results.map(group => {
return html`<option value=${ifDefined(group.pk)} ?selected=${this.provider?.searchGroup === group.pk}>${group.name}</option>`;
});
}), html`<option>${t`Loading...`}</option>`)}
</select>
<p class="pf-c-form__helper-text">${t`Users in the selected group can do search queries.`}</p>
</ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">