providers/scim: correctly handle 404 by re-creating object (#5405)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L 2023-04-28 14:36:21 +03:00 committed by GitHub
parent 967a38b7ac
commit ecce31ee87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 13 deletions

View File

@ -14,7 +14,7 @@ from requests import RequestException, Session
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
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 ResourceMissing, SCIMRequestException
from authentik.providers.scim.models import SCIMProvider from authentik.providers.scim.models import SCIMProvider
T = TypeVar("T") T = TypeVar("T")
@ -73,6 +73,8 @@ class SCIMClient(Generic[T, SchemaType]):
raise SCIMRequestException(None) from exc raise SCIMRequestException(None) from exc
self.logger.debug("scim request", path=path, method=method, **kwargs) self.logger.debug("scim request", path=path, method=method, **kwargs)
if response.status_code >= 400: if response.status_code >= 400:
if response.status_code == 404:
raise ResourceMissing(response)
self.logger.warning( self.logger.warning(
"Failed to send SCIM request", path=path, method=method, response=response.text "Failed to send SCIM request", path=path, method=method, response=response.text
) )

View File

@ -41,3 +41,8 @@ class SCIMRequestException(SentryIgnoredException):
except ValidationError: except ValidationError:
pass pass
return super().__str__() return super().__str__()
class ResourceMissing(SCIMRequestException):
"""Error raised when the provider raises a 404, meaning that we
should delete our internal ID and re-create the object"""

View File

@ -10,7 +10,7 @@ from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
from authentik.policies.utils import delete_none_keys from authentik.policies.utils import delete_none_keys
from authentik.providers.scim.clients.base import SCIMClient from authentik.providers.scim.clients.base import SCIMClient
from authentik.providers.scim.clients.exceptions import StopSync from authentik.providers.scim.clients.exceptions import ResourceMissing, StopSync
from authentik.providers.scim.clients.schema import Group as SCIMGroupSchema from authentik.providers.scim.clients.schema import Group as SCIMGroupSchema
from authentik.providers.scim.models import SCIMGroup, SCIMMapping, SCIMUser from authentik.providers.scim.models import SCIMGroup, SCIMMapping, SCIMUser
@ -23,15 +23,11 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
scim_group = SCIMGroup.objects.filter(provider=self.provider, group=obj).first() scim_group = SCIMGroup.objects.filter(provider=self.provider, group=obj).first()
if not scim_group: if not scim_group:
return self._create(obj) return self._create(obj)
scim_group = self.to_scim(obj) try:
scim_group.id = scim_group.id return self._update(obj, scim_group)
return self._request( except ResourceMissing:
"PUT", scim_group.delete()
f"/Groups/{scim_group.id}", return self._create(obj)
data=scim_group.json(
exclude_unset=True,
),
)
def delete(self, obj: Group): def delete(self, obj: Group):
"""Delete group""" """Delete group"""
@ -104,6 +100,18 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
) )
SCIMGroup.objects.create(provider=self.provider, group=group, id=response["id"]) SCIMGroup.objects.create(provider=self.provider, group=group, id=response["id"])
def _update(self, group: Group, connection: SCIMGroup):
"""Update existing group"""
scim_group = self.to_scim(group)
scim_group.id = connection.id
return self._request(
"PUT",
f"/Groups/{scim_group.id}",
data=scim_group.json(
exclude_unset=True,
),
)
def _patch( def _patch(
self, self,
group_id: str, group_id: str,

View File

@ -8,7 +8,7 @@ from authentik.events.models import Event, EventAction
from authentik.lib.utils.errors import exception_to_string from authentik.lib.utils.errors import exception_to_string
from authentik.policies.utils import delete_none_keys from authentik.policies.utils import delete_none_keys
from authentik.providers.scim.clients.base import SCIMClient from authentik.providers.scim.clients.base import SCIMClient
from authentik.providers.scim.clients.exceptions import StopSync from authentik.providers.scim.clients.exceptions import ResourceMissing, StopSync
from authentik.providers.scim.clients.schema import User as SCIMUserSchema from authentik.providers.scim.clients.schema import User as SCIMUserSchema
from authentik.providers.scim.models import SCIMMapping, SCIMUser from authentik.providers.scim.models import SCIMMapping, SCIMUser
@ -21,7 +21,11 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first() scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first()
if not scim_user: if not scim_user:
return self._create(obj) return self._create(obj)
return self._update(obj, scim_user) try:
return self._update(obj, scim_user)
except ResourceMissing:
scim_user.delete()
return self._create(obj)
def delete(self, obj: User): def delete(self, obj: User):
"""Delete user""" """Delete user"""