basic SSE-KMS support
Florent Viard authored on 2015/09/18 01:36:33... | ... |
@@ -29,6 +29,7 @@ class Config(object): |
29 | 29 |
access_token = "" |
30 | 30 |
host_base = "s3.amazonaws.com" |
31 | 31 |
host_bucket = "%(bucket)s.s3.amazonaws.com" |
32 |
+ kms_key = "" #can't set this and Server Side Encryption at the same time |
|
32 | 33 |
simpledb_host = "sdb.amazonaws.com" |
33 | 34 |
cloudfront_host = "cloudfront.amazonaws.com" |
34 | 35 |
verbosity = logging.WARNING |
... | ... |
@@ -155,6 +156,12 @@ class Config(object): |
155 | 155 |
self.secret_key = env_secret_key |
156 | 156 |
else: |
157 | 157 |
self.role_config() |
158 |
+ |
|
159 |
+ #TODO check KMS key is valid |
|
160 |
+ if self.kms_key and self.server_side_encryption == True: |
|
161 |
+ warning('Cannot have server_side_encryption (S3 SSE) and KMS_key set (S3 KMS). KMS encryption will be used. Please set server_side_encryption to False') |
|
162 |
+ if self.kms_key and self.signature_v2 == True: |
|
163 |
+ raise Exception('KMS encryption requires signature v4. Please set signature_v2 to False') |
|
158 | 164 |
|
159 | 165 |
def role_config(self): |
160 | 166 |
if sys.version_info[0] * 10 + sys.version_info[1] < 26: |
... | ... |
@@ -573,6 +573,11 @@ class S3(object): |
573 | 573 |
if self.config.server_side_encryption: |
574 | 574 |
headers["x-amz-server-side-encryption"] = "AES256" |
575 | 575 |
|
576 |
+ ####inject in kms headers |
|
577 |
+ if self.config.kms_key: |
|
578 |
+ headers['x-amz-server-side-encryption'] = 'aws:kms' |
|
579 |
+ headers['x-amz-server-side-encryption-aws-kms-key-id'] = self.config.kms_key |
|
580 |
+ |
|
576 | 581 |
## MIME-type handling |
577 | 582 |
headers["content-type"] = self.content_type(filename=filename) |
578 | 583 |
|
... | ... |
@@ -725,6 +730,11 @@ class S3(object): |
725 | 725 |
if self.config.server_side_encryption: |
726 | 726 |
headers["x-amz-server-side-encryption"] = "AES256" |
727 | 727 |
|
728 |
+ ####inject in kms headers |
|
729 |
+ if self.config.kms_key: |
|
730 |
+ headers['x-amz-server-side-encryption'] = 'aws:kms' |
|
731 |
+ headers['x-amz-server-side-encryption-aws-kms-key-id'] = self.config.kms_key |
|
732 |
+ |
|
728 | 733 |
if extra_headers: |
729 | 734 |
headers.update(extra_headers) |
730 | 735 |
|
... | ... |
@@ -759,7 +769,12 @@ class S3(object): |
759 | 759 |
## Set server side encryption |
760 | 760 |
if self.config.server_side_encryption: |
761 | 761 |
headers["x-amz-server-side-encryption"] = "AES256" |
762 |
- |
|
762 |
+ |
|
763 |
+ ####inject in kms headers |
|
764 |
+ if self.config.kms_key: |
|
765 |
+ headers['x-amz-server-side-encryption'] = 'aws:kms' |
|
766 |
+ headers['x-amz-server-side-encryption-aws-kms-key-id'] = self.config.kms_key |
|
767 |
+ |
|
763 | 768 |
if extra_headers: |
764 | 769 |
headers.update(extra_headers) |
765 | 770 |
|
... | ... |
@@ -1265,7 +1280,8 @@ class S3(object): |
1265 | 1265 |
raise S3Error(response) |
1266 | 1266 |
|
1267 | 1267 |
debug("MD5 sums: computed=%s, received=%s" % (md5_computed, response["headers"]["etag"])) |
1268 |
- if response["headers"]["etag"].strip('"\'') != md5_hash.hexdigest(): |
|
1268 |
+ ## when using KMS encryption, MD5 etag value will not match |
|
1269 |
+ if (response["headers"]["etag"].strip('"\'') != md5_hash.hexdigest()) and response["headers"]["x-amz-server-side-encryption"] != 'aws:kms': |
|
1269 | 1270 |
warning("MD5 Sums don't match!") |
1270 | 1271 |
if retries: |
1271 | 1272 |
warning("Retrying upload of %s" % (filename)) |
... | ... |
@@ -1464,8 +1480,9 @@ class S3(object): |
1464 | 1464 |
warning("Reported size (%s) does not match received size (%s)" % ( |
1465 | 1465 |
start_position + long(response["headers"]["content-length"]), response["size"])) |
1466 | 1466 |
debug("ReceiveFile: Computed MD5 = %s" % response.get("md5")) |
1467 |
+ debug("sse headers : %s" % response["headers"]["x-amz-server-side-encryption"]) |
|
1467 | 1468 |
# avoid ETags from multipart uploads that aren't the real md5 |
1468 |
- if '-' not in md5_from_s3 and not response["md5match"]: |
|
1469 |
+ if ('-' not in md5_from_s3 and not response["md5match"]) and (response["headers"]["x-amz-server-side-encryption"] != 'aws:kms'): |
|
1469 | 1470 |
warning("MD5 signatures do not match: computed=%s, received=%s" % ( |
1470 | 1471 |
response.get("md5"), md5_from_s3)) |
1471 | 1472 |
return response |