Skip to content

Commit f228217

Browse files
authored
Merge pull request #5 from fjelltopp/handle_s3_403
wrc104 Handle S3 403
2 parents 3a05768 + e54ae45 commit f228217

File tree

6 files changed

+33
-69
lines changed

6 files changed

+33
-69
lines changed

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-20.04
1313
strategy:
1414
matrix:
15-
python-version: [ 3.7, 3.8 ]
15+
python-version: [ 3.8 ]
1616
steps:
1717
- uses: actions/checkout@v2
1818
- name: Install Python 3

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
language: python
22

33
python:
4-
- 3.7
54
- 3.8
65

76
env:

Dockerfile

Lines changed: 0 additions & 64 deletions
This file was deleted.

giftless/error_handling.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
33
See https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#response-errors
44
"""
5+
import logging
6+
57
from werkzeug.exceptions import default_exceptions
68

79
from .representation import output_git_lfs_json
10+
from .storage.exc import AccessDenied
811

912

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

23+
# Specifically handle AccessDenied with a JSON response and 403 status
24+
app.errorhandler(AccessDenied)(self.access_denied_as_json)
25+
2026
@classmethod
2127
def error_as_json(cls, ex):
2228
"""Handle errors by returning a JSON response
29+
only maps HTTP-based exceptions from werkzeug.exceptions (like NotFound or Forbidden)
2330
"""
31+
log = logging.getLogger(__name__)
2432
code = ex.code if hasattr(ex, 'code') else 500
2533
data = {"message": str(ex)}
34+
log.debug(f"Returning error response: {data} with status {code}")
2635

2736
return output_git_lfs_json(data=data, code=code)
37+
38+
@classmethod
39+
def access_denied_as_json(cls, ex):
40+
"""Handle AccessDenied by returning a JSON response with 403 status"""
41+
log = logging.getLogger(__name__)
42+
log.debug("Returning error response of AccessDenied with status 403")
43+
data = ex.as_dict()
44+
return output_git_lfs_json(data=data, code=403)

giftless/storage/amazon_s3.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import botocore # type: ignore
66

77
from giftless.storage import ExternalStorage, StreamingStorage
8-
from giftless.storage.exc import ObjectNotFound
8+
from giftless.storage.exc import AccessDenied, ObjectNotFound
99
from giftless.util import safe_filename
1010

1111

@@ -22,7 +22,13 @@ def __init__(self, bucket_name: str, path_prefix: Optional[str] = None, **_):
2222
def get(self, prefix: str, oid: str) -> Iterable[bytes]:
2323
if not self.exists(prefix, oid):
2424
raise ObjectNotFound()
25-
result: Iterable[bytes] = self._s3_object(prefix, oid).get()['Body']
25+
try:
26+
result: Iterable[bytes] = self._s3_object(prefix, oid).get()['Body']
27+
except botocore.exceptions.ClientError as e:
28+
if e.response['Error']['Code'] in ("403", "AccessDenied"):
29+
raise AccessDenied()
30+
else:
31+
raise e
2632
return result
2733

2834
def put(self, prefix: str, oid: str, data_stream: BinaryIO) -> int:
@@ -38,7 +44,7 @@ def upload_callback(size):
3844
def exists(self, prefix: str, oid: str) -> bool:
3945
try:
4046
self.get_size(prefix, oid)
41-
except ObjectNotFound:
47+
except (ObjectNotFound, AccessDenied):
4248
return False
4349
return True
4450

@@ -48,6 +54,8 @@ def get_size(self, prefix: str, oid: str) -> int:
4854
except botocore.exceptions.ClientError as e:
4955
if e.response['Error']['Code'] == "404":
5056
raise ObjectNotFound()
57+
elif e.response['Error']['Code'] in ("403", "AccessDenied"):
58+
raise AccessDenied()
5159
else:
5260
raise e
5361
return result

giftless/storage/exc.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ class ObjectNotFound(StorageError):
1919

2020
class InvalidObject(StorageError):
2121
code = 422
22+
23+
24+
class AccessDenied(StorageError):
25+
code = 403

0 commit comments

Comments
 (0)