Skip to content

Commit

Permalink
Merge pull request #5 from fjelltopp/handle_s3_403
Browse files Browse the repository at this point in the history
wrc104 Handle S3 403
  • Loading branch information
mixmixmix authored Nov 14, 2024
2 parents 3a05768 + e54ae45 commit f228217
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 69 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
python-version: [ 3.7, 3.8 ]
python-version: [ 3.8 ]
steps:
- uses: actions/checkout@v2
- name: Install Python 3
Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
language: python

python:
- 3.7
- 3.8

env:
Expand Down
64 changes: 0 additions & 64 deletions Dockerfile

This file was deleted.

17 changes: 17 additions & 0 deletions giftless/error_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
See https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#response-errors
"""
import logging

from werkzeug.exceptions import default_exceptions

from .representation import output_git_lfs_json
from .storage.exc import AccessDenied


class ApiErrorHandler:
Expand All @@ -17,11 +20,25 @@ def init_app(self, app):
for code in default_exceptions:
app.errorhandler(code)(self.error_as_json)

# Specifically handle AccessDenied with a JSON response and 403 status
app.errorhandler(AccessDenied)(self.access_denied_as_json)

@classmethod
def error_as_json(cls, ex):
"""Handle errors by returning a JSON response
only maps HTTP-based exceptions from werkzeug.exceptions (like NotFound or Forbidden)
"""
log = logging.getLogger(__name__)
code = ex.code if hasattr(ex, 'code') else 500
data = {"message": str(ex)}
log.debug(f"Returning error response: {data} with status {code}")

return output_git_lfs_json(data=data, code=code)

@classmethod
def access_denied_as_json(cls, ex):
"""Handle AccessDenied by returning a JSON response with 403 status"""
log = logging.getLogger(__name__)
log.debug("Returning error response of AccessDenied with status 403")
data = ex.as_dict()
return output_git_lfs_json(data=data, code=403)
14 changes: 11 additions & 3 deletions giftless/storage/amazon_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import botocore # type: ignore

from giftless.storage import ExternalStorage, StreamingStorage
from giftless.storage.exc import ObjectNotFound
from giftless.storage.exc import AccessDenied, ObjectNotFound
from giftless.util import safe_filename


Expand All @@ -22,7 +22,13 @@ def __init__(self, bucket_name: str, path_prefix: Optional[str] = None, **_):
def get(self, prefix: str, oid: str) -> Iterable[bytes]:
if not self.exists(prefix, oid):
raise ObjectNotFound()
result: Iterable[bytes] = self._s3_object(prefix, oid).get()['Body']
try:
result: Iterable[bytes] = self._s3_object(prefix, oid).get()['Body']
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] in ("403", "AccessDenied"):
raise AccessDenied()
else:
raise e
return result

def put(self, prefix: str, oid: str, data_stream: BinaryIO) -> int:
Expand All @@ -38,7 +44,7 @@ def upload_callback(size):
def exists(self, prefix: str, oid: str) -> bool:
try:
self.get_size(prefix, oid)
except ObjectNotFound:
except (ObjectNotFound, AccessDenied):
return False
return True

Expand All @@ -48,6 +54,8 @@ def get_size(self, prefix: str, oid: str) -> int:
except botocore.exceptions.ClientError as e:
if e.response['Error']['Code'] == "404":
raise ObjectNotFound()
elif e.response['Error']['Code'] in ("403", "AccessDenied"):
raise AccessDenied()
else:
raise e
return result
Expand Down
4 changes: 4 additions & 0 deletions giftless/storage/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,7 @@ class ObjectNotFound(StorageError):

class InvalidObject(StorageError):
code = 422


class AccessDenied(StorageError):
code = 403

0 comments on commit f228217

Please sign in to comment.