Skip to content

Commit 6a11e79

Browse files
dschnellertimvaillancourt
authored andcommitted
Option to Allow skipping bucket validation (#287)
* Option to fix "S3ResponseError: 403 Forbidden" The S3 uploader fails if bucket permissions are restricted to only allow accessing certain prefixes in a bucket. The default behavior for boto's "get_bucket()" is to "validate" it by accessing the bucket's root, needlessly breaking the uploader even though all necessary permissions might be present. This patch adds a new command line switch --upload.s3.skip_bucket_validation to disable this behavior. * Related: Fix flake8: Make regex a raw string * Fix indentation
1 parent d771961 commit 6a11e79

File tree

4 files changed

+24
-13
lines changed

4 files changed

+24
-13
lines changed

mongodb_consistent_backup/Upload/S3/S3.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def __init__(self, manager, config, timer, base_dir, backup_dir, **kwargs):
2323
self.chunk_size = self.chunk_size_mb * 1024 * 1024
2424
self.s3_acl = self.config.upload.s3.acl
2525
self.key_prefix = base_dir
26+
self.validate_bucket = not self.config.upload.s3.skip_bucket_validation
2627

2728
self.threads(self.config.upload.threads)
2829
self._pool = None
@@ -38,7 +39,8 @@ def __init__(self, manager, config, timer, base_dir, backup_dir, **kwargs):
3839
self.threads(),
3940
self.remove_uploaded,
4041
self.chunk_size,
41-
self.s3_acl
42+
self.s3_acl,
43+
validate_bucket=self.validate_bucket
4244
)
4345

4446
def get_key_name(self, file_path):

mongodb_consistent_backup/Upload/S3/S3Session.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88

99

1010
class S3Session:
11-
def __init__(self, region, access_key, secret_key, bucket_name, secure=True, num_retries=5, socket_timeout=15):
12-
self.region = region
13-
self.access_key = access_key
14-
self.secret_key = secret_key
15-
self.secure = secure
16-
self.num_retries = num_retries
17-
self.socket_timeout = socket_timeout
18-
11+
def __init__(self, region, access_key, secret_key, bucket_name, secure=True, num_retries=5, socket_timeout=15,
12+
**kwargs):
13+
self.region = region
14+
self.access_key = access_key
15+
self.secret_key = secret_key
16+
self.secure = secure
17+
self.num_retries = num_retries
18+
self.socket_timeout = socket_timeout
19+
self.validate_bucket = kwargs.get("validate_bucket")
1920
# monkey patch for bucket_name with dots
2021
# https://github.com/boto/boto/issues/2836
2122
if self.secure and '.' in bucket_name:
@@ -77,8 +78,10 @@ def connect(self):
7778

7879
def get_bucket(self, bucket_name):
7980
try:
80-
logging.debug("Connecting to AWS S3 Bucket: %s" % bucket_name)
81-
return self._conn.get_bucket(bucket_name)
81+
logging.debug("Connecting to AWS S3 Bucket: %s (%s validation)" % (bucket_name,
82+
"with" if self.validate_bucket
83+
else "without"))
84+
return self._conn.get_bucket(bucket_name, validate=self.validate_bucket)
8285
except boto.exception.S3ResponseError, e:
8386
if self.is_forbidden_error(e):
8487
logging.error("Got forbidden error from AWS S3 for bucket %s! Please check your access/secret key" % bucket_name)

mongodb_consistent_backup/Upload/S3/S3UploadPool.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def _reduce_method(m):
2828

2929

3030
class S3UploadPool():
31-
def __init__(self, bucket_name, region, access_key, secret_key, threads=4, remove_uploaded=False, chunk_bytes=50 * 1024 * 1024, key_acl=None):
31+
def __init__(self, bucket_name, region, access_key, secret_key, threads=4, remove_uploaded=False, chunk_bytes=50 * 1024 * 1024, key_acl=None, **kwargs):
3232
self.bucket_name = bucket_name
3333
self.region = region
3434
self.access_key = access_key
@@ -37,6 +37,7 @@ def __init__(self, bucket_name, region, access_key, secret_key, threads=4, remov
3737
self.remove_uploaded = remove_uploaded
3838
self.chunk_bytes = chunk_bytes
3939
self.key_acl = key_acl
40+
self.validate_bucket = kwargs.get("validate_bucket")
4041

4142
self.multipart_min_bytes = 5242880
4243

@@ -46,7 +47,8 @@ def __init__(self, bucket_name, region, access_key, secret_key, threads=4, remov
4647
self._pool = Pool(processes=self.threads)
4748

4849
try:
49-
self.s3_conn = S3Session(self.region, self.access_key, self.secret_key, self.bucket_name)
50+
self.s3_conn = S3Session(self.region, self.access_key, self.secret_key, self.bucket_name,
51+
validate_bucket=self.validate_bucket)
5052
self.bucket = self.s3_conn.get_bucket(self.bucket_name)
5153
except Exception, e:
5254
raise OperationError(e)

mongodb_consistent_backup/Upload/S3/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ def config(parser):
1010
help="S3 Uploader AWS Secret Key (required for S3 upload)")
1111
parser.add_argument("--upload.s3.bucket_name", dest="upload.s3.bucket_name", type=str,
1212
help="S3 Uploader destination bucket name")
13+
parser.add_argument("--upload.s3.skip_bucket_validation", dest="upload.s3.skip_bucket_validation", default=False,
14+
action="store_true",
15+
help="S3 Upload will check upfront if the bucket exists. Skip this check if bucket "
16+
"permissions don't allow access to the bucket's root. (default: false)")
1317
parser.add_argument("--upload.s3.bucket_prefix", dest="upload.s3.bucket_prefix", type=str,
1418
help="S3 Uploader destination bucket path prefix")
1519
parser.add_argument("--upload.s3.bucket_explicit_key", dest="upload.s3.bucket_explicit_key", type=str,

0 commit comments

Comments
 (0)