I don’t know what happened in the last 24 hours that caused this thing to break, but it had been working perfectly for 3 years, non stop without issues. Trust me, I haven’t changed any code. As a matter of fact, I haven’t pushed code for 2 weeks.
Basically, I am using Laravel 6 and Laravel Vapor to upload files to S3 using the Signed URLs mechanism that the framework provides. Ever since this morning, I am seeing the following issue. The AWS PHP SDK is 3.148.3, by the way.
<Error>
<Code>SignatureDoesNotMatch</Code>
<Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message>
<AWSAccessKeyId>[REDACTED]</AWSAccessKeyId>
<StringToSign>AWS4-HMAC-SHA256 20220712T203731Z 20220712/eu-west-2/s3/aws4_request 961d5d32676be187af1a7ccf8a92b8c29e2d851bdd51c46836aedce7cc9e089a</StringToSign>
<SignatureProvided>101e80ad27bfe4ed12a34b19fff4c17f87a3f639b92d62c8e7a79b13c876b1ca</SignatureProvided>
<StringToSignBytes>41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 0a 32 30 32 32 30 37 31 32 54 32 30 33 37 33 31 5a 0a 32 30 32 32 30 37 31 32 2f 65 75 2d 77 65 73 74 2d 32 2f 73 33 2f 61 77 73 34 5f 72 65 71 75 65 73 74 0a 39 36 31 64 35 64 33 32 36 37 36 62 65 31 38 37 61 66 31 61 37 63 63 66 38 61 39 32 62 38 63 32 39 65 32 64 38 35 31 62 64 64 35 31 63 34 36 38 33 36 61 65 64 63 65 37 63 63 39 65 30 38 39 61</StringToSignBytes>
<CanonicalRequest>GET /tmp/0344aa31-c756-49c3-8ce1-932ec23c895d X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=[REDACTED]%2F20220712%2Feu-west-2%2Fs3%2Faws4_request&X-Amz-Date=20220712T203731Z&X-Amz-Expires=300&X-Amz-SignedHeaders=host%3Bx-amz-acl&x-amz-acl=public-read host:[REDACTED].s3.eu-west-2.amazonaws.com x-amz-acl:public-read host;x-amz-acl UNSIGNED-PAYLOAD</CanonicalRequest>
<CanonicalRequestBytes>47 45 54 0a 2f 74 6d 70 2f 30 33 34 34 61 61 33 31 2d 63 37 35 36 2d 34 39 63 33 2d 38 63 65 31 2d 39 33 32 65 63 32 33 63 38 39 35 64 0a 58 2d 41 6d 7a 2d 41 6c 67 6f 72 69 74 68 6d 3d 41 57 53 34 2d 48 4d 41 43 2d 53 48 41 32 35 36 26 58 2d 41 6d 7a 2d 43 6f 6e 74 65 6e 74 2d 53 68 61 32 35 36 3d 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44 26 58 2d 41 6d 7a 2d 43 72 65 64 65 6e 74 69 61 6c 3d 41 4b 49 41 34 58 4b 4a 50 55 57 34 55 43 42 4a 49 32 57 57 25 32 46 32 30 32 32 30 37 31 32 25 32 46 65 75 2d 77 65 73 74 2d 32 25 32 46 73 33 25 32 46 61 77 73 34 5f 72 65 71 75 65 73 74 26 58 2d 41 6d 7a 2d 44 61 74 65 3d 32 30 32 32 30 37 31 32 54 32 30 33 37 33 31 5a 26 58 2d 41 6d 7a 2d 45 78 70 69 72 65 73 3d 33 30 30 26 58 2d 41 6d 7a 2d 53 69 67 6e 65 64 48 65 61 64 65 72 73 3d 68 6f 73 74 25 33 42 78 2d 61 6d 7a 2d 61 63 6c 26 78 2d 61 6d 7a 2d 61 63 6c 3d 70 75 62 6c 69 63 2d 72 65 61 64 0a 68 6f 73 74 3a 73 68 61 64 6f 77 66 6f 75 6e 64 72 2d 75 70 6c 6f 61 64 73 2d 6c 6f 63 61 6c 2e 73 33 2e 65 75 2d 77 65 73 74 2d 32 2e 61 6d 61 7a 6f 6e 61 77 73 2e 63 6f 6d 0a 78 2d 61 6d 7a 2d 61 63 6c 3a 70 75 62 6c 69 63 2d 72 65 61 64 0a 0a 68 6f 73 74 3b 78 2d 61 6d 7a 2d 61 63 6c 0a 55 4e 53 49 47 4e 45 44 2d 50 41 59 4c 4f 41 44</CanonicalRequestBytes>
<RequestId>S6E8RFNVQ3WGAAHB</RequestId>
<HostId>yA998rWcqzfVIdD9HyrIJRJtbI/ge5opCEHEgpPoBBAuwRjgABub590OnA66JVHwyxHdo/a2uB6+ii/IxwZIGw==</HostId>
</Error>
Vue.js
@change=upload
convertFileNameToKebabCase(fileNameRaw) {
let fileNameActual = _.kebabCase(fileNameRaw.split(".").shift());
let fileExtension = fileNameRaw.split(".").pop();
return `${fileNameActual}.${fileExtension}`;
},
async store(file, options = {}, fileAcl) {
const response = await Vue.axios.post(
"/vapor/signed-storage-url", {
bucket: options.bucket || "",
content_type: options.contentType || file.type,
expires: options.expires || "",
visibility: fileAcl || "",
ignore_web_middleware: true
}, {
baseURL: options.baseURL || null,
headers: options.headers || {}
}
);
let headers = response.data.headers;
if ("Host" in headers) {
delete headers.Host;
}
if (typeof options.progress === "undefined") {
options.progress = () => {};
}
// Reset axios instance as Amazon
// does not like our Auth header
const newInstance = axios.create();
await newInstance.put(response.data.url, file, {
headers: headers,
onUploadProgress: progressEvent => {
options.progress(
progressEvent.loaded / progressEvent.total
);
}
});
response.data.extension = file.name.split(".").pop();
return response.data;
},
async upload(event) {
const {
valid
} = await this.$refs.provider.validate(event);
if (valid) {
this.reset();
let fileData = this.$refs.file.files[0];
this.fileName = fileData.name;
this.url = false;
try {
const response = await this.store(
this.$refs.file.files[0], {
progress: progress => {
this.uploadProgress = Math.round(progress * 100);
}
},
"public-read"
);
Vue.axios
.post("/file/commit", {
uuid: response.uuid,
key: response.key,
bucket: response.bucket,
name: this.convertFileNameToKebabCase(this.$refs.file.files[0].name),
content_type: this.$refs.file.files[0].type
})
.then(success => {
this.reset();
this.url = success.data.data.file;
this.uploadCompleted = true;
})
.catch(error => {
this.reset();
this.uploadFailed = true;
});
} catch (error) {
this.reset();
this.uploadFailed = true;
}
}
},
2
Answers
I found the solution. I had to remove the following in the headers:
x-amz-acl
. I do not know why this was the problem but it seems to have worked. Hope if anyone comes across this in the future, try this solution.Three things to check:
profile, check if access key and secret are still valid.
<AllowedHeader>*</AllowedHeader>
Otherwise could you share some more details on the code that causes the error?