)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90737251c3d3552fb6a7d6d1530ecbabad10e49","unresolved":true,"context_lines":[{"line_number":4,"context_line":"Commit:     Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2026-08-27 13:56:13 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"s3api: don\u0027t base64-validate checksum values on POST"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"S3Request already declines to verify a request checksum on any POST"},{"line_number":10,"context_line":"other than DeleteObjects, because S3 doesn\u0027t check the body checksum"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"10778a13_bd7b65d3","line":7,"range":{"start_line":7,"start_character":7,"end_line":7,"end_character":52},"updated":"2026-08-27 17:58:13.000000000","message":"IIUC this is an existing bug?? Do we have a functional test (maybe that could be pulled forward in a reduced form from later in the chain) that would fail with 400 without this patch? i.e. do a CompleteMultipartUpload with COMPOSITE checksum value?","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"fbb3bce3917ea2da9f1eaa2b3586f69cfb36c99a","unresolved":true,"context_lines":[{"line_number":4,"context_line":"Commit:     Nathaniel Martes \u003cnmartes@NVIDIA.com\u003e"},{"line_number":5,"context_line":"CommitDate: 2026-08-27 13:56:13 +0000"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"s3api: don\u0027t base64-validate checksum values on POST"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"S3Request already declines to verify a request checksum on any POST"},{"line_number":10,"context_line":"other than DeleteObjects, because S3 doesn\u0027t check the body checksum"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"e1ff566e_59619f4e","line":7,"range":{"start_line":7,"start_character":7,"end_line":7,"end_character":52},"in_reply_to":"10778a13_bd7b65d3","updated":"2026-08-27 18:41:11.000000000","message":"Yes this is an existing bug... not sure if we need a launchpad bug for it since we are already not handling checksum MPU rules\n\n\u003e Do we have a functional test (maybe that could be pulled forward in a reduced form from later in the chain)\n\nWe do, I think pulling them forward and adding a\n```\n# XXX: Swift does not accept final checksum value for validation that is composite \u003cb64\u003e-\u003ccount\u003e when AWS does\n```","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90737251c3d3552fb6a7d6d1530ecbabad10e49","unresolved":true,"context_lines":[{"line_number":9,"context_line":"S3Request already declines to verify a request checksum on any POST"},{"line_number":10,"context_line":"other than DeleteObjects, because S3 doesn\u0027t check the body checksum"},{"line_number":11,"context_line":"for operations such as CompleteMultipartUpload. The early value check"},{"line_number":12,"context_line":"in _validate_checksum_headers() didn\u0027t follow that decision, so a POST"},{"line_number":13,"context_line":"carrying a checksum value that isn\u0027t raw base64 was rejected with"},{"line_number":14,"context_line":"InvalidRequest even though the value was never going to be checked."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"Gate the early check on the same condition. A checksum header on a POST"},{"line_number":17,"context_line":"is now either validated and verified, or left alone, which lets a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"dad30191_8d89d936","line":14,"range":{"start_line":12,"start_character":61,"end_line":14,"end_character":67},"updated":"2026-08-27 17:58:13.000000000","message":"Can we add the specific example:\n\n```\nFor example, a CompleteMultipartUpload request with a COMPOSITE type checksum value of the form \u003cbase64\u003e-\u003cnum_parts\u003e would previously have received a 400 response.\n```","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90737251c3d3552fb6a7d6d1530ecbabad10e49","unresolved":true,"context_lines":[{"line_number":11,"context_line":"for operations such as CompleteMultipartUpload. The early value check"},{"line_number":12,"context_line":"in _validate_checksum_headers() didn\u0027t follow that decision, so a POST"},{"line_number":13,"context_line":"carrying a checksum value that isn\u0027t raw base64 was rejected with"},{"line_number":14,"context_line":"InvalidRequest even though the value was never going to be checked."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"Gate the early check on the same condition. A checksum header on a POST"},{"line_number":17,"context_line":"is now either validated and verified, or left alone, which lets a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"0bb7ab78_2d59cca2","line":14,"updated":"2026-08-27 17:58:13.000000000","message":"so is this telling us that no client has been sending MPU complete\u0027s citing composite checksum values? cos they\u0027d have got a 400 if they did?","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"fbb3bce3917ea2da9f1eaa2b3586f69cfb36c99a","unresolved":true,"context_lines":[{"line_number":11,"context_line":"for operations such as CompleteMultipartUpload. The early value check"},{"line_number":12,"context_line":"in _validate_checksum_headers() didn\u0027t follow that decision, so a POST"},{"line_number":13,"context_line":"carrying a checksum value that isn\u0027t raw base64 was rejected with"},{"line_number":14,"context_line":"InvalidRequest even though the value was never going to be checked."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"Gate the early check on the same condition. A checksum header on a POST"},{"line_number":17,"context_line":"is now either validated and verified, or left alone, which lets a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"4ca0c0ae_a0a0a765","line":14,"in_reply_to":"0bb7ab78_2d59cca2","updated":"2026-08-27 18:41:11.000000000","message":"The SDKs they use have not, probably because they do not compute the final checksum for validation, relying on S3 to do it for them. Also because even if they did the \u0027-\u003ccount\u003e\u0027 in a composite checksum, is optional by S3","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"df072136728c91ec4baddbdf686613e2ff03beb4","unresolved":false,"context_lines":[{"line_number":9,"context_line":"S3Request already declines to verify a request checksum on any POST"},{"line_number":10,"context_line":"other than DeleteObjects, because S3 doesn\u0027t check the body checksum"},{"line_number":11,"context_line":"for operations such as CompleteMultipartUpload. The early value check"},{"line_number":12,"context_line":"in _validate_checksum_headers() didn\u0027t follow that decision, so a POST"},{"line_number":13,"context_line":"carrying a checksum value that isn\u0027t raw base64 was rejected with"},{"line_number":14,"context_line":"InvalidRequest even though the value was never going to be checked."},{"line_number":15,"context_line":""},{"line_number":16,"context_line":"Gate the early check on the same condition. A checksum header on a POST"},{"line_number":17,"context_line":"is now either validated and verified, or left alone, which lets a"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":9,"id":"a40e173f_2562f559","line":14,"range":{"start_line":12,"start_character":61,"end_line":14,"end_character":67},"in_reply_to":"dad30191_8d89d936","updated":"2026-08-27 22:01:36.000000000","message":"Done","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"3cc101ad68ef165737136d4b638094c2869075ed","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"42c86a06_bc56f5a5","updated":"2026-08-25 20:10:03.000000000","message":"This was pulled out for 993193: s3api: Checksum Persistence on MPUs | https://review.opendev.org/c/openstack/swift/+/993193 to make reviewing this patch easier","commit_id":"f482d09a858fe3c01dba6c42c0cda650ef3d2f65"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90737251c3d3552fb6a7d6d1530ecbabad10e49","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":9,"id":"a9d27538_1d5cfc08","updated":"2026-08-27 17:58:13.000000000","message":"-1 may seem harsh but I think having one boolean flag to gate the two tightly coupled paths is significant. See 1002677: sq? s3request validate POST checksum fixup | https://review.opendev.org/c/openstack/swift/+/1002677","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cea84b86538f1289eb3bc1a533cca557dae5d95a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"ab337d59_742a3ec8","updated":"2026-08-28 10:58:35.000000000","message":"IIUC this is fixing an existing bug on master and could be merged straight to master","commit_id":"7c9065ef5131cb1639b89d6f02086044d292c6ea"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"d1addc34fa8a480bb87b1fcbe1246beade18a1f2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":10,"id":"a4cf3ef6_c24554d0","updated":"2026-08-27 22:01:11.000000000","message":"Some things here\n\n* move this lower on the chain so that we could get it approved faster... no big need for it to be after 1002405: s3api: Checksum Persistence on CreateMultipartUpload and UploadPart | https://review.opendev.org/c/openstack/swift/+/1002405\n\n* squashed in the changes from 1002677: sq? s3request validate POST checksum fixup | https://review.opendev.org/c/openstack/swift/+/1002677\n\n* Add comapt test to showcase behavior","commit_id":"7c9065ef5131cb1639b89d6f02086044d292c6ea"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"aecf156fcab4c83ad5ec72fcb7e21c74aa6e478f","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":12,"id":"74531f68_f0e25506","updated":"2026-08-28 11:49:51.000000000","message":"LGTM.","commit_id":"094beb844f83cbfc2a6243afdc4b979d49a38845"}],"swift/common/middleware/s3api/s3request.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90737251c3d3552fb6a7d6d1530ecbabad10e49","unresolved":true,"context_lines":[{"line_number":1074,"context_line":"        if self.method in (\u0027PUT\u0027, \u0027POST\u0027):"},{"line_number":1075,"context_line":"            # A checksum that validates a request body must be raw base64."},{"line_number":1076,"context_line":"            # Controllers that interpret it as an operation result may apply"},{"line_number":1077,"context_line":"            # their own value format validation."},{"line_number":1078,"context_line":"            validate_value \u003d ("},{"line_number":1079,"context_line":"                self.method \u003d\u003d \u0027PUT\u0027 or \u0027delete\u0027 in self.params)"},{"line_number":1080,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"}],"source_content_type":"text/x-python","patch_set":9,"id":"8feb9df3_8194b54c","line":1077,"updated":"2026-08-27 17:58:13.000000000","message":"I found the comment a little vague. The existing comment at line 1105 could be improved to cover things.","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"df072136728c91ec4baddbdf686613e2ff03beb4","unresolved":false,"context_lines":[{"line_number":1074,"context_line":"        if self.method in (\u0027PUT\u0027, \u0027POST\u0027):"},{"line_number":1075,"context_line":"            # A checksum that validates a request body must be raw base64."},{"line_number":1076,"context_line":"            # Controllers that interpret it as an operation result may apply"},{"line_number":1077,"context_line":"            # their own value format validation."},{"line_number":1078,"context_line":"            validate_value \u003d ("},{"line_number":1079,"context_line":"                self.method \u003d\u003d \u0027PUT\u0027 or \u0027delete\u0027 in self.params)"},{"line_number":1080,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"}],"source_content_type":"text/x-python","patch_set":9,"id":"3c4cace7_417d768d","line":1077,"in_reply_to":"8feb9df3_8194b54c","updated":"2026-08-27 22:01:36.000000000","message":"Done","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"f90737251c3d3552fb6a7d6d1530ecbabad10e49","unresolved":true,"context_lines":[{"line_number":1076,"context_line":"            # Controllers that interpret it as an operation result may apply"},{"line_number":1077,"context_line":"            # their own value format validation."},{"line_number":1078,"context_line":"            validate_value \u003d ("},{"line_number":1079,"context_line":"                self.method \u003d\u003d \u0027PUT\u0027 or \u0027delete\u0027 in self.params)"},{"line_number":1080,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"},{"line_number":1081,"context_line":"                self._validate_checksum_headers(validate_value)"},{"line_number":1082,"context_line":"            if _is_streaming(aws_sha256):"}],"source_content_type":"text/x-python","patch_set":9,"id":"eadde036_e0ac25aa","line":1079,"updated":"2026-08-27 17:58:13.000000000","message":"This is the same condition as ``verify_checksum`` flags below. We could, and should, use the same boolean to gate both paths, to ensure they never diverge.","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"df072136728c91ec4baddbdf686613e2ff03beb4","unresolved":false,"context_lines":[{"line_number":1076,"context_line":"            # Controllers that interpret it as an operation result may apply"},{"line_number":1077,"context_line":"            # their own value format validation."},{"line_number":1078,"context_line":"            validate_value \u003d ("},{"line_number":1079,"context_line":"                self.method \u003d\u003d \u0027PUT\u0027 or \u0027delete\u0027 in self.params)"},{"line_number":1080,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"},{"line_number":1081,"context_line":"                self._validate_checksum_headers(validate_value)"},{"line_number":1082,"context_line":"            if _is_streaming(aws_sha256):"}],"source_content_type":"text/x-python","patch_set":9,"id":"aa66afb3_a3078619","line":1079,"in_reply_to":"396c93aa_c75c3227","updated":"2026-08-27 22:01:36.000000000","message":"Done","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"},{"author":{"_account_id":39146,"name":"Nathaniel Martes","display_name":"Nate Martes","email":"nmartes@NVIDIA.com","username":"nmartes"},"change_message_id":"fbb3bce3917ea2da9f1eaa2b3586f69cfb36c99a","unresolved":true,"context_lines":[{"line_number":1076,"context_line":"            # Controllers that interpret it as an operation result may apply"},{"line_number":1077,"context_line":"            # their own value format validation."},{"line_number":1078,"context_line":"            validate_value \u003d ("},{"line_number":1079,"context_line":"                self.method \u003d\u003d \u0027PUT\u0027 or \u0027delete\u0027 in self.params)"},{"line_number":1080,"context_line":"            checksum_hasher, checksum_header, checksum_trailer \u003d \\"},{"line_number":1081,"context_line":"                self._validate_checksum_headers(validate_value)"},{"line_number":1082,"context_line":"            if _is_streaming(aws_sha256):"}],"source_content_type":"text/x-python","patch_set":9,"id":"396c93aa_c75c3227","line":1079,"in_reply_to":"eadde036_e0ac25aa","updated":"2026-08-27 18:41:11.000000000","message":"Yes that would be good, it sucks having two things in multiple places","commit_id":"62e4431de37cd3f85d71d535f7fdbfb9eb5742d5"}],"test/s3api/test_object_checksums.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"cea84b86538f1289eb3bc1a533cca557dae5d95a","unresolved":true,"context_lines":[{"line_number":951,"context_line":"        self.assertEqual(204, abort_resp["},{"line_number":952,"context_line":"            \u0027ResponseMetadata\u0027][\u0027HTTPStatusCode\u0027])"},{"line_number":953,"context_line":""},{"line_number":954,"context_line":"    def test_multipart_mpu_composite_checksum(self):"},{"line_number":955,"context_line":"        obj_name \u003d self.create_name(\u0027composite-checksum-mpu\u0027)"},{"line_number":956,"context_line":"        create_mpu_resp \u003d self.client.create_multipart_upload("},{"line_number":957,"context_line":"            Bucket\u003dself.bucket_name, Key\u003dobj_name,"}],"source_content_type":"text/x-python","patch_set":10,"id":"30bd2f4c_491c2aed","line":954,"updated":"2026-08-28 10:58:35.000000000","message":"passes against S3 \n```\n% SWIFT_TEST_AWS_CONFIG_FILE\u003d~/.aws/credentials pytest test/s3api/test_object_checksums.py -k test_multipart_mpu_composite_checksum\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d test session starts \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nplatform darwin -- Python 3.8.15, pytest-8.3.5, pluggy-1.5.0 -- /Users/acoles/.pyenv/versions/3.8.15/envs/swift-3.8.15/bin/python3.8\ncachedir: .pytest_cache\nrootdir: /Users/acoles/0dev/openstack/swift\nconfigfile: tox.ini\nplugins: cov-2.12.1, repeat-0.9.3, reverse-1.7.0, subtests-0.13.1, flake8-1.1.0\ncollected 58 items / 57 deselected / 1 selected\n\ntest/s3api/test_object_checksums.py::TestObjectChecksums::test_multipart_mpu_composite_checksum PASSED                                 [100%]\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d 1 passed, 57 deselected in 25.56s \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\n```\n\nfails on vsaio when change is reverted\n\n```\nE           botocore.errorfactory.InvalidRequest: An error occurred (InvalidRequest) when calling the CompleteMultipartUpload operation: Value for x-amz-checksum-crc32 header is invalid.\n\n/usr/local/lib/python3.10/dist-packages/botocore/client.py:1078: InvalidRequest\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d short test summary info \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nFAILED test/s3api/test_object_checksums.py::TestObjectChecksums::test_multipart_mpu_composite_checksum - botocore.errorfactory.InvalidRequest: An error occurred (InvalidRequest) when calling the CompleteMultipartUpload operation: Value for x-amz-checksum-crc32 he...\n```","commit_id":"7c9065ef5131cb1639b89d6f02086044d292c6ea"}]}
