goauthentik / authentik

The authentication glue you need.
https://goauthentik.io
Other
13.49k stars 900 forks source link

Stack trace on 403 for s3 storage backend #11939

Open 4d62 opened 1 day ago

4d62 commented 1 day ago

Describe the bug When attempting to add an icon to an application when the storage backend is S3, a stack trace is returned if the status code is 403.

To Reproduce Steps to reproduce the behavior:

  1. Set the env variables defined in 'Additional context' section of this issue
  2. Misconfigure your S3 provider (?)
  3. Visit the Admin interface > applications > applications > and try to add an icon after clicking Edit > UI settings

Expected behavior The icon is successfully added to the s3 bucket or an error is returned to the user.

Screenshots If applicable, add screenshots to help explain your problem.

Logs

{"auth_via": "session", "domain_url": "id.sdko.org", "event": "/api/v3/core/applications/gitea-gitbackup/", "host": "id.sdko.org", "level": "info", "logger": "authentik.asgi", "method": "PUT", "pid": 93, "remote": "MYIP", "request_id": "c8d0c5be20be4bebac5645233f2252dc", "runtime": 826, "schema_name": "public", "scheme": "https", "status": 200, "timestamp": "2024-11-06T17:38:32.319509", "user": "MYUSER", "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0"}
{"action": "system_exception", "auth_via": "session", "client_ip": "MYIP", "context": {"asn": {"as_org": "X", "asn": 1, "network": "xx"}, "geo": {"city": "x", "continent": "x", "country": "x", "lat": 4 "long": -1}, "http_request": {"args": {}, "method": "POST", "path": "/api/v3/core/applications/gitea-gitbackup/set_icon/", "request_id": "7fcdd191c39b44c7a05c3a856a3296f0", "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0"}, "message": "Traceback (most recent call last):\n  File \"/ak-root/venv/lib/python3.12/site-packages/asgiref/sync.py\", line 518, in thread_handler\n    raise exc_info[1]\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/core/handlers/base.py\", line 253, in _get_response_async\n    response = await wrapped_callback(\n               ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/asgiref/sync.py\", line 468, in __call__\n    ret = await asyncio.shield(exec_coro)\n          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/asgiref/current_thread_executor.py\", line 40, in run\n    result = self.fn(*self.args, **self.kwargs)\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/asgiref/sync.py\", line 522, in thread_handler\n    return func(*args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py\", line 90, in sentry_wrapped_callback\n    return callback(request, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/views/decorators/csrf.py\", line 65, in _view_wrapper\n    return view_func(request, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/rest_framework/viewsets.py\", line 125, in view\n    return self.dispatch(request, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py\", line 509, in dispatch\n    response = self.handle_exception(exc)\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py\", line 469, in handle_exception\n    self.raise_uncaught_exception(exc)\n  File \"/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py\", line 480, in raise_uncaught_exception\n    raise exc\n  File \"/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py\", line 506, in dispatch\n    response = handler(request, *args, **kwargs)\n               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/authentik/rbac/decorators.py\", line 39, in wrapper\n    return func(self, request, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/authentik/core/api/applications.py\", line 304, in set_icon\n    return set_file(request, app, \"meta_icon\")\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/authentik/lib/utils/file.py\", line 40, in set_file\n    obj.save()\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py\", line 822, in save\n    self.save_base(\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py\", line 909, in save_base\n    updated = self._save_table(\n              ^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py\", line 1035, in _save_table\n    (getattr(self, f.attname) if raw else f.pre_save(self, False)),\n                                          ^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/db/models/fields/files.py\", line 324, in pre_save\n    file.save(file.name, file.file, save=False)\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/db/models/fields/files.py\", line 94, in save\n    self.name = self.storage.save(name, content, max_length=self.field.max_length)\n                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/core/files/storage/base.py\", line 44, in save\n    name = self.get_available_name(name, max_length=max_length)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/django/core/files/storage/base.py\", line 88, in get_available_name\n    while self.exists(name) or (max_length and len(name) > max_length):\n          ^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/storages/backends/s3.py\", line 587, in exists\n    self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)\n  File \"/ak-root/venv/lib/python3.12/site-packages/botocore/client.py\", line 565, in _api_call\n    return self._make_api_call(operation_name, kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/ak-root/venv/lib/python3.12/site-packages/botocore/client.py\", line 1017, in _make_api_call\n    raise error_class(parsed_response, operation_name)\nbotocore.exceptions.ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden"}, "domain_url": "id.sdko.org", "event": "Created Event", "host": "id.sdko.org", "level": "info", "logger": "authentik.events.models", "pid": 93, "request_id": "7fcdd191c39b44c7a05c3a856a3296f0", "schema_name": "public", "timestamp": "2024-11-06T17:38:33.296588", "user": {"email": "x", "pk": 7, "username": "x"}}

Version and Deployment (please complete the following information):

Additional context Stack trace:

Traceback (most recent call last):
  File "/ak-root/venv/lib/python3.12/site-packages/asgiref/sync.py", line 518, in thread_handler
    raise exc_info[1]
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               ^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/asgiref/sync.py", line 468, in __call__
    ret = await asyncio.shield(exec_coro)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/asgiref/current_thread_executor.py", line 40, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/asgiref/sync.py", line 522, in thread_handler
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/sentry_sdk/integrations/django/views.py", line 90, in sentry_wrapped_callback
    return callback(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/ak-root/venv/lib/python3.12/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/rbac/decorators.py", line 39, in wrapper
    return func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/core/api/applications.py", line 304, in set_icon
    return set_file(request, app, "meta_icon")
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/lib/utils/file.py", line 40, in set_file
    obj.save()
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py", line 822, in save
    self.save_base(
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py", line 909, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/base.py", line 1035, in _save_table
    (getattr(self, f.attname) if raw else f.pre_save(self, False)),
                                          ^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/fields/files.py", line 324, in pre_save
    file.save(file.name, file.file, save=False)
  File "/ak-root/venv/lib/python3.12/site-packages/django/db/models/fields/files.py", line 94, in save
    self.name = self.storage.save(name, content, max_length=self.field.max_length)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/files/storage/base.py", line 44, in save
    name = self.get_available_name(name, max_length=max_length)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/django/core/files/storage/base.py", line 88, in get_available_name
    while self.exists(name) or (max_length and len(name) > max_length):
          ^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/storages/backends/s3.py", line 587, in exists
    self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
  File "/ak-root/venv/lib/python3.12/site-packages/botocore/client.py", line 565, in _api_call
    return self._make_api_call(operation_name, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/ak-root/venv/lib/python3.12/site-packages/botocore/client.py", line 1017, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (403) when calling the HeadObject operation: Forbidden

relevant .env:

AUTHENTIK_STORAGE__MEDIA__BACKEND=s3
AUTHENTIK_STORAGE__MEDIA__S3__USE_SSL=true
AUTHENTIK_STORAGE__MEDIA__S3__ENDPOINT=https://objstr.sdko.org
AUTHENTIK_STORAGE__MEDIA__S3__ACCESS_KEY=x
AUTHENTIK_STORAGE__MEDIA__S3__SECRET_KEY=x
AUTHENTIK_STORAGE__MEDIA__S3__BUCKET_NAME=authentik-prod
AUTHENTIK_STORAGE__MEDIA__S3__CUSTOM_DOMAIN=objstr.sdko.org/authentik-prod
AUTHENTIK_STORAGE__MEDIA__S3__SECURE_URLS=true
4d62 commented 4 hours ago

Oh forgot to mention, probably doesn't change anything for fixing the issue but it was related to having Cloudflare infront of my minio (https://stackoverflow.com/a/76608351