providers/scim: add compatibility mode for AWS & Slack (#13342)
* providers/scim: override AWS patch support AWS /ServiceProviderConfig query responds that it supports patch, but they only support patching a single group property. resolves #12321 * introduce compatibility mode for scim provider instead of hack Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space> * add option for slack Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space> Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space> Co-authored-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
@ -28,6 +28,7 @@ class SCIMProviderSerializer(ProviderSerializer):
|
|||||||
"url",
|
"url",
|
||||||
"verify_certificates",
|
"verify_certificates",
|
||||||
"token",
|
"token",
|
||||||
|
"compatibility_mode",
|
||||||
"exclude_users_service_account",
|
"exclude_users_service_account",
|
||||||
"filter_group",
|
"filter_group",
|
||||||
"dry_run",
|
"dry_run",
|
||||||
|
|||||||
@ -22,7 +22,7 @@ from authentik.lib.sync.outgoing.exceptions import (
|
|||||||
from authentik.lib.utils.http import get_http_session
|
from authentik.lib.utils.http import get_http_session
|
||||||
from authentik.providers.scim.clients.exceptions import SCIMRequestException
|
from authentik.providers.scim.clients.exceptions import SCIMRequestException
|
||||||
from authentik.providers.scim.clients.schema import ServiceProviderConfiguration
|
from authentik.providers.scim.clients.schema import ServiceProviderConfiguration
|
||||||
from authentik.providers.scim.models import SCIMProvider
|
from authentik.providers.scim.models import SCIMCompatibilityMode, SCIMProvider
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
@ -90,9 +90,14 @@ class SCIMClient[TModel: "Model", TConnection: "Model", TSchema: "BaseModel"](
|
|||||||
"""Get Service provider config"""
|
"""Get Service provider config"""
|
||||||
default_config = ServiceProviderConfiguration.default()
|
default_config = ServiceProviderConfiguration.default()
|
||||||
try:
|
try:
|
||||||
return ServiceProviderConfiguration.model_validate(
|
config = ServiceProviderConfiguration.model_validate(
|
||||||
self._request("GET", "/ServiceProviderConfig")
|
self._request("GET", "/ServiceProviderConfig")
|
||||||
)
|
)
|
||||||
|
if self.provider.compatibility_mode == SCIMCompatibilityMode.AWS:
|
||||||
|
config.patch.supported = False
|
||||||
|
if self.provider.compatibility_mode == SCIMCompatibilityMode.SLACK:
|
||||||
|
config.filter.supported = True
|
||||||
|
return config
|
||||||
except (ValidationError, SCIMRequestException, NotFoundSyncException) as exc:
|
except (ValidationError, SCIMRequestException, NotFoundSyncException) as exc:
|
||||||
self.logger.warning("failed to get ServiceProviderConfig", exc=exc)
|
self.logger.warning("failed to get ServiceProviderConfig", exc=exc)
|
||||||
return default_config
|
return default_config
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 5.0.12 on 2025-03-07 23:35
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_providers_scim", "0011_scimprovider_dry_run"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="scimprovider",
|
||||||
|
name="compatibility_mode",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[("default", "Default"), ("aws", "AWS"), ("slack", "Slack")],
|
||||||
|
default="default",
|
||||||
|
help_text="Alter authentik behavior for vendor-specific SCIM implementations.",
|
||||||
|
max_length=30,
|
||||||
|
verbose_name="SCIM Compatibility Mode",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@ -57,6 +57,14 @@ class SCIMProviderGroup(SerializerModel):
|
|||||||
return f"SCIM Provider Group {self.group_id} to {self.provider_id}"
|
return f"SCIM Provider Group {self.group_id} to {self.provider_id}"
|
||||||
|
|
||||||
|
|
||||||
|
class SCIMCompatibilityMode(models.TextChoices):
|
||||||
|
"""SCIM compatibility mode"""
|
||||||
|
|
||||||
|
DEFAULT = "default", _("Default")
|
||||||
|
AWS = "aws", _("AWS")
|
||||||
|
SLACK = "slack", _("Slack")
|
||||||
|
|
||||||
|
|
||||||
class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
||||||
"""SCIM 2.0 provider to create users and groups in external applications"""
|
"""SCIM 2.0 provider to create users and groups in external applications"""
|
||||||
|
|
||||||
@ -77,6 +85,14 @@ class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
|||||||
help_text=_("Property mappings used for group creation/updating."),
|
help_text=_("Property mappings used for group creation/updating."),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
compatibility_mode = models.CharField(
|
||||||
|
max_length=30,
|
||||||
|
choices=SCIMCompatibilityMode.choices,
|
||||||
|
default=SCIMCompatibilityMode.DEFAULT,
|
||||||
|
verbose_name=_("SCIM Compatibility Mode"),
|
||||||
|
help_text=_("Alter authentik behavior for vendor-specific SCIM implementations."),
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon_url(self) -> str | None:
|
def icon_url(self) -> str | None:
|
||||||
return static("authentik/sources/scim.png")
|
return static("authentik/sources/scim.png")
|
||||||
|
|||||||
@ -6661,6 +6661,16 @@
|
|||||||
"title": "Token",
|
"title": "Token",
|
||||||
"description": "Authentication token"
|
"description": "Authentication token"
|
||||||
},
|
},
|
||||||
|
"compatibility_mode": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"default",
|
||||||
|
"aws",
|
||||||
|
"slack"
|
||||||
|
],
|
||||||
|
"title": "SCIM Compatibility Mode",
|
||||||
|
"description": "Alter authentik behavior for vendor-specific SCIM implementations."
|
||||||
|
},
|
||||||
"exclude_users_service_account": {
|
"exclude_users_service_account": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"title": "Exclude users service account"
|
"title": "Exclude users service account"
|
||||||
|
|||||||
21
schema.yml
21
schema.yml
@ -41582,6 +41582,12 @@ components:
|
|||||||
- confidential
|
- confidential
|
||||||
- public
|
- public
|
||||||
type: string
|
type: string
|
||||||
|
CompatibilityModeEnum:
|
||||||
|
enum:
|
||||||
|
- default
|
||||||
|
- aws
|
||||||
|
- slack
|
||||||
|
type: string
|
||||||
Config:
|
Config:
|
||||||
type: object
|
type: object
|
||||||
description: Serialize authentik Config into DRF Object
|
description: Serialize authentik Config into DRF Object
|
||||||
@ -52441,6 +52447,11 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: Authentication token
|
description: Authentication token
|
||||||
|
compatibility_mode:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/CompatibilityModeEnum'
|
||||||
|
title: SCIM Compatibility Mode
|
||||||
|
description: Alter authentik behavior for vendor-specific SCIM implementations.
|
||||||
exclude_users_service_account:
|
exclude_users_service_account:
|
||||||
type: boolean
|
type: boolean
|
||||||
filter_group:
|
filter_group:
|
||||||
@ -55841,6 +55852,11 @@ components:
|
|||||||
token:
|
token:
|
||||||
type: string
|
type: string
|
||||||
description: Authentication token
|
description: Authentication token
|
||||||
|
compatibility_mode:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/CompatibilityModeEnum'
|
||||||
|
title: SCIM Compatibility Mode
|
||||||
|
description: Alter authentik behavior for vendor-specific SCIM implementations.
|
||||||
exclude_users_service_account:
|
exclude_users_service_account:
|
||||||
type: boolean
|
type: boolean
|
||||||
filter_group:
|
filter_group:
|
||||||
@ -55931,6 +55947,11 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: Authentication token
|
description: Authentication token
|
||||||
|
compatibility_mode:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/CompatibilityModeEnum'
|
||||||
|
title: SCIM Compatibility Mode
|
||||||
|
description: Alter authentik behavior for vendor-specific SCIM implementations.
|
||||||
exclude_users_service_account:
|
exclude_users_service_account:
|
||||||
type: boolean
|
type: boolean
|
||||||
filter_group:
|
filter_group:
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { html } from "lit";
|
|||||||
import { ifDefined } from "lit/directives/if-defined.js";
|
import { ifDefined } from "lit/directives/if-defined.js";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
CompatibilityModeEnum,
|
||||||
CoreApi,
|
CoreApi,
|
||||||
CoreGroupsListRequest,
|
CoreGroupsListRequest,
|
||||||
Group,
|
Group,
|
||||||
@ -61,6 +62,35 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
|
|||||||
)}
|
)}
|
||||||
inputHint="code"
|
inputHint="code"
|
||||||
></ak-text-input>
|
></ak-text-input>
|
||||||
|
<ak-radio-input
|
||||||
|
name="compatibilityMode"
|
||||||
|
label=${msg("Compatibility Mode")}
|
||||||
|
.value=${provider?.compatibilityMode}
|
||||||
|
required
|
||||||
|
.options=${[
|
||||||
|
{
|
||||||
|
label: msg("Default"),
|
||||||
|
value: CompatibilityModeEnum.Default,
|
||||||
|
default: true,
|
||||||
|
description: html`${msg("Default behavior.")}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: msg("AWS"),
|
||||||
|
value: CompatibilityModeEnum.Aws,
|
||||||
|
description: html`${msg(
|
||||||
|
"Altered behavior for usage with Amazon Web Services.",
|
||||||
|
)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: msg("Slack"),
|
||||||
|
value: CompatibilityModeEnum.Slack,
|
||||||
|
description: html`${msg("Altered behavior for usage with Slack.")}`,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
help=${msg(
|
||||||
|
"Alter authentik's behavior for vendor-specific SCIM implementations.",
|
||||||
|
)}
|
||||||
|
></ak-radio-input>
|
||||||
<ak-form-element-horizontal name="dryRun">
|
<ak-form-element-horizontal name="dryRun">
|
||||||
<label class="pf-c-switch">
|
<label class="pf-c-switch">
|
||||||
<input
|
<input
|
||||||
|
|||||||
Reference in New Issue
Block a user