providers/scim: correctly handle 404 by re-creating object (#5405)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
967a38b7ac
commit
ecce31ee87
|
@ -14,7 +14,7 @@ from requests import RequestException, Session
|
|||
from structlog.stdlib import get_logger
|
||||
|
||||
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
|
||||
|
||||
T = TypeVar("T")
|
||||
|
@ -73,6 +73,8 @@ class SCIMClient(Generic[T, SchemaType]):
|
|||
raise SCIMRequestException(None) from exc
|
||||
self.logger.debug("scim request", path=path, method=method, **kwargs)
|
||||
if response.status_code >= 400:
|
||||
if response.status_code == 404:
|
||||
raise ResourceMissing(response)
|
||||
self.logger.warning(
|
||||
"Failed to send SCIM request", path=path, method=method, response=response.text
|
||||
)
|
||||
|
|
|
@ -41,3 +41,8 @@ class SCIMRequestException(SentryIgnoredException):
|
|||
except ValidationError:
|
||||
pass
|
||||
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"""
|
||||
|
|
|
@ -10,7 +10,7 @@ from authentik.events.models import Event, EventAction
|
|||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
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.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()
|
||||
if not scim_group:
|
||||
return self._create(obj)
|
||||
scim_group = self.to_scim(obj)
|
||||
scim_group.id = scim_group.id
|
||||
return self._request(
|
||||
"PUT",
|
||||
f"/Groups/{scim_group.id}",
|
||||
data=scim_group.json(
|
||||
exclude_unset=True,
|
||||
),
|
||||
)
|
||||
try:
|
||||
return self._update(obj, scim_group)
|
||||
except ResourceMissing:
|
||||
scim_group.delete()
|
||||
return self._create(obj)
|
||||
|
||||
def delete(self, obj: Group):
|
||||
"""Delete group"""
|
||||
|
@ -104,6 +100,18 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
|
|||
)
|
||||
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(
|
||||
self,
|
||||
group_id: str,
|
||||
|
|
|
@ -8,7 +8,7 @@ from authentik.events.models import Event, EventAction
|
|||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.policies.utils import delete_none_keys
|
||||
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.models import SCIMMapping, SCIMUser
|
||||
|
||||
|
@ -21,7 +21,11 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
|
|||
scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first()
|
||||
if not scim_user:
|
||||
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):
|
||||
"""Delete user"""
|
||||
|
|
Reference in a new issue