JarvisWorks
JarvisWorks

Reputation: 63

cURL to AWS S3 using AppleScript

I'm using AppleScript and shell to curl files from my local system to an AWS S3 bucket. I'm able to accomplish this calling a bash script from AppleScript, but when I try to use strictly AppleScript I get a "SignatureDoesNotMatch" error from AWS.

Anybody see what might be wrong?

There is an existing thread on this where the OP encountered the same problem then finally gave up on this method and used PHP.

AppleScript do shell script cURL command for Amazon s3

My code:

--File info
set filePath to "/Volumes/MyFolder"
set fileName to "001.jpg"

--AWS Info
set awsRegion to "s3-us-west-1"
set bucketName to "mybucketname"
set awsPath to "mysubfolder"
set s3key to "myawskey"
set s3secret to "myawssecretkey"

--Build cannonical request
set acl to "x-amz-acl:public-read"
set contentType to "application/octet-stream"
set storageType to "x-amz-storage-class:STANDARD"
--set theDate to do shell script "date '+%a, %d %b %Y %T %z'"
set theDate to do shell script "date -R"
set connonicalString to "PUT\\n\\n" & contentType & "\\n" & theDate & "\\n" & acl & "\\n" & storageType & "\\n/" & bucketName & "/" & awsPath & "/" & fileName
set signatureCommand to "echo -en " & connonicalString & " | openssl sha1 -hmac " & s3secret & " -binary | base64"
set signature to do shell script signatureCommand

--Build the curl command
set curlCommand to "curl -s -X PUT"
set sourcePath to " -T " & filePath & "/" & fileName
set header01 to " -H 'Host: " & bucketName & "." & awsRegion & ".amazonaws.com'"
set header02 to " -H 'Date: " & theDate & "'"
set header03 to " -H 'Content-Type: " & contentType & "'"
set header04 to " -H '" & storageType & "'"
set header05 to " -H '" & acl & "'"
set header06 to " -H 'Authorization: AWS " & s3key & ":" & signature & "'"
set targetPath to " https://" & bucketName & "." & awsRegion & ".amazonaws.com/" & awsPath & "/" & fileName

set shellCommand to curlCommand & sourcePath & header01 & header02 & header03 & header04 & header05 & header06 & targetPath

--Run the script
do shell script shellCommand

Here is the error:

SignatureDoesNotMatchThe request signature we calculated does not match the signature you provided. Check your key and signing method....

Upvotes: 0

Views: 344

Answers (1)

foo4thought
foo4thought

Reputation: 11

The problem you cite is due to the shell being used by applescript: it's /bin/sh but your terminal emulator is probably using BASH (/bin/bash). Therein, the echo used in /bin/sh seems not to accept switches!
i.e., "-en " got rolled into what becomes applescript variable |connonicalString|

Either substitute for echo -en with printf %s (no trailing space!) or use heredoc syntax for variable signatureCommand for its use in do shell script signatureCommand

set signatureCommand to "/bin/bash <<EOF
echo -en " & connonicalString & " | openssl sha1 -hmac " & s3secret & " -binary | base64
EOF"

Compare this output done in a terminal window running BASH:

Last login: Tue Mar 24 12:17:22 on ttys003
mylocal:~ myself$ echo -en PUT\n\napplication/octet-stream\nTue, 24 Mar 2020 16:07:09 -0400\nx-amz-acl:public-read\nx-amz-storage-class:STANDARD\n/mybucketname/mysubfolder/001.jpg | openssl sha1 -hmac myawssecretkey -binary | base64

CpUNJTkp6i1ocERz7PQ+Q/m5rYI=

With this output done in a terminal window running /bin/sh:

mylocal:~ myself$ /bin/sh
mylocal:~ myself$ echo -en PUT\n\napplication/octet-stream\nTue, 24 Mar 2020 16:07:09 -0400\nx-amz-acl:public-read\nx-amz-storage-class:STANDARD\n/mybucketname/mysubfolder/001.jpg | openssl sha1 -hmac myawssecretkey -binary | base64

Wy1tNXiDmDsdlm/sBDDYCoc0kik=

Then observe what is the output in Script Editor using its default /bin/sh:

tell current application
    do shell script "date -R"
        --> "Tue, 24 Mar 2020 16:07:09 -0400"
    do shell script "echo -en PUT\\n\\napplication/octet-stream\\nTue, 24 Mar 2020 16:07:09 -0400\\nx-amz-acl:public-read\\nx-amz-storage-class:STANDARD\\n/mybucketname/mysubfolder/001.jpg | openssl sha1 -hmac myawssecretkey -binary | base64"
        --> "Wy1tNXiDmDsdlm/sBDDYCoc0kik="
end tell
Result:
"Wy1tNXiDmDsdlm/sBDDYCoc0kik="

and then forcing it to use /bin/bash:

tell current application
    do shell script "date -R"
        --> "Tue, 24 Mar 2020 16:46:47 -0400"
    do shell script "/bin/bash <<EOF
echo -en PUT\\n\\napplication/octet-stream\\nTue, 24 Mar 2020 16:07:09 -0400\\nx-amz-acl:public-read\\nx-amz-storage-class:STANDARD\\n/mybucketname/mysubfolder/001.jpg | openssl sha1 -hmac myawssecretkey -binary | base64
EOF"
        --> "CpUNJTkp6i1ocERz7PQ+Q/m5rYI="
end tell
Result:
"CpUNJTkp6i1ocERz7PQ+Q/m5rYI="

Upvotes: 1

Related Questions