1. create an amazon file upload policy document to allow uploads by users of audio files visible to the world.
2. using this policy document create a policy signature that can be used by web clients to http post/upload an mp3 file.
3. a demo command line client that will upload a sample file to your amazon s3 bucket.
K first off we're gonna assume you set up an amazon bucket, have an access_key and secret_access_key, pretty easy to do just head on over to the AWS management web console and set it up.
We'll also assume you have some file named test.mp3 you want to upload to s3.
In this demo I'll be using:
bucket=dreamlogs
sub_folder=folder # this is the subfolder where files will be uploaded.
AMAZON_ACCESS_KEY_ID=your_key
AMAZON_SECRET_ACCESS_KEY=you_secret_key
filename=test.mp3
Now we need to create an amazon s3 post policy that determines who has access to upload files to your bucket. There are many different kinds of policies with amazon web services so in this case you need something like the following:
This site got me started but seems to be pretty out of date, the doc links are dead:
http://s3.amazonaws.com/doc/s3-example-code/post/post_sample.html
Here's an example:
{ "expiration": "repl_expiration",
"conditions": [
{"bucket": "repl_bucket" },
{"acl": "repl_acl" },
["eq", "$key", "repl_foldername/repl_username/repl_filename"],
["content-length-range", 0, "repl_max_content_bytes"],
["starts-with", "$Content-Type", "repl_content_type"],
{"redirect": "repl_s3url/repl_bucket/repl_foldername/repl_username/repl_filename"},
]
}
every variable starting with the word repl shoul be replaced with whatever permission you are trying to allow, here's what I put in my java .properties file.
BUCKET=bucketname
UPLOADDIR=somedir
CONTENT_TYPE=application/octet-stream
S3URL=http://s3.amazonaws.com
ACL=public-read
# example 20 megabytes would be 20 * 1048576 = 20971520 bytes
MAX_CONTENT_BYTES=20971520
Next up we need to remove carriage returns / line feeds then B64 encode this policy.
Finally sign it with our amazon secret key. The following is the main brain of my java web service its response is Json object with the policy and signature necessary for the client to then use to formulate a post file upload request to amazon s3.
1 package my awsconsole proj web;
2
3 import javatext SimpleDateFormat;
4 import java utilDate;
5 import java util TimeZone;
6
7 import javax management timer Timer;
8 import javax servlet http HttpServletRequest;
9
10 import my awsconsole projdomain PolicySignature;
11 import my awsconsole proj tooling PolicyGenerator;
12
13 import org apache log4j Logger;
14 import org springframework roo addon web mvc controller RooWebScaffold;
15 import org springframework stereotype Controller;
16 import org springframework web bind annotation RequestMapping;
17 import org springframework web bind annotation RequestMethod;
18 import org springframework web bind annotation RequestParam;
19 import org springframework web bind annotation ResponseBody;
20
21
22 @RooWebScaffold path = "policysignatures" formBackingObject = PolicySignatureclass update = falsedelete = false create = false
23 @RequestMapping"/policysignatures"
24 @Controller
25 public class PolicySignatureService
26
27 private static Logger logger = Logger getLogger PolicySignatureServiceclass;
28
29
30 @RequestMapping value = "/service" method = RequestMethod GET headers = "Accept=application/json"
31 @ResponseBody
32 public Object showJson @RequestParam value = "facebook_id" required = true String facebook_id
33 @RequestParam value = "filename" required = true String filename
34 HttpServletRequest request
35 PolicyGenerator generator = ;
36 String formattedExpirationDate = getFormattedExpirationDate;
37 String generatedPolicy = makeAWSPostPolicy facebook_id filename generator formattedExpirationDate;
38 String b64EncodedPolicy = generator b64EncodePolicy generatedPolicy;
39 String signature = generator signPolicy generator AWSSECRETKEY b64EncodedPolicy;
40 PolicySignature policysignature = makePolicySignature facebook_id
41 filename generator b64EncodedPolicy signature;
42 logger.info request getRemoteAddr+","+ generatedPolicy +","+ policysignature toJson;
43 return policysignature toJson;
44
45
46
47 public PolicySignature makePolicySignatureString facebook_id
48 String filename PolicyGenerator generatorString b64EncodedPolicy
49 String signature
50 PolicySignature policysignature = ;
51 policysignature setPolicy b64EncodedPolicy;
52 policysignature setSignature signature;
53 policysignature setAWSAccessKeyId generator AWSKEYID;
54 policysignature setBucket generator BUCKET;
55 policysignature setFkey generator UPLOADDIR+"/"+facebook_id+"/"+filename;
56 policysignature setContent_type generator CONTENT_TYPE;
57 policysignature setFile"@" + filename;
58 policysignature setS3url generator S3URL + "/" + generator BUCKET;
59 policysignature setRedirect generator S3URL + "/" + generator BUCKET + "/" + generator UPLOADDIR + "/" + facebook_id + "/" + filename;
60 policysignature setAcl generator ACL;
61 return policysignature;
62
63
64
65 public String makeAWSPostPolicyString facebook_idString filename
66 PolicyGenerator generatorString formattedExpirationDate
67 String generatedPolicy = generator generatePolicy generator AWSKEYID generator AWSSECRETKEY;
68 generatedPolicy = generatedPolicy replaceAll"repl_expiration" formattedExpirationDate;
69 generatedPolicy = generatedPolicy replaceAll"repl_bucket" generator BUCKET;
70 generatedPolicy = generatedPolicy replaceAll"repl_acl" generator ACL;
71 generatedPolicy = generatedPolicy replaceAll"repl_filename" filename;
72 generatedPolicy = generatedPolicy replaceAll"repl_content_type" generator CONTENT_TYPE;
73 generatedPolicy = generatedPolicy replaceAll"repl_max_content_bytes" generator MAX_CONTENT_BYTES;
74 generatedPolicy = generatedPolicy replaceAll"repl_foldername" generator UPLOADDIR;
75 generatedPolicy = generatedPolicy replaceAll"repl_username" facebook_id;
76 generatedPolicy = generatedPolicy replaceAll"repl_s3url" generator S3URL;
77 generatedPolicy = generatedPolicy replaceAll"\r""";
78 generatedPolicy = generatedPolicy replaceAll"\n""";
79 return generatedPolicy;
80
81
82
83 public String getFormattedExpirationDate
84 Date now = ;
85 Date oneHourFromNow = nowgetTime + Timer ONE_HOUR;
86 TimeZone tz = TimeZone getTimeZone "UTC" ;
87 SimpleDateFormat dfm = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
88 dfm setTimeZone tz ;
89 String formattedExpirationDate = dfm format oneHourFromNow;
90 return formattedExpirationDate;
91
92
93
The signing code and base 64 code was modeled after this security doc: http://docs.amazonwebservices.com/AWSSimpleQueueService/2007-05-01/SQSDeveloperGuide/SummaryOfAuthentication.html
package my awsconsole proj tooling;
import java io IOException;
import java io InputStream;
import javasecurity SignatureException;
import java util Properties;
public class PolicyGenerator
public String BUCKET;
public String DEFAULT_AMAZON_POLICY;
public String AWSKEYID;
public String UPLOADDIR;
public String CONTENT_TYPE;
public String S3URL;
public String AWSSECRETKEY;
public String ACL;
public String MAX_CONTENT_BYTES;
public PolicyGenerator
InputStream policyInputStream = PolicyGeneratorclass getClassLoader getResourceAsStream"permissive.json";
InputStream bucketingInputStream = PolicyGeneratorclass getClassLoader getResourceAsStream"amazon_bucketing.properties";
InputStream credentialsInputStream = PolicyGeneratorclass getClassLoader getResourceAsStream"AwsCredentials.properties";
byte bytes = null;
try
bytes = policyInputStream available;
policyInputStream read bytes;
DEFAULT_AMAZON_POLICY = bytes;
Properties awsprops = ;
awspropsload bucketingInputStream;
BUCKET = awsprops getProperty"BUCKET";
UPLOADDIR = awsprops getProperty"UPLOADDIR";
CONTENT_TYPE = awsprops getProperty"CONTENT_TYPE";
S3URL = awsprops getProperty"S3URL";
ACL = awsprops getProperty"ACL";
MAX_CONTENT_BYTES = awsprops getProperty"MAX_CONTENT_BYTES";
Properties awscreds = ;
awscredsload credentialsInputStream;
AWSKEYID = awscreds getProperty"accessKey";
AWSSECRETKEY = awscreds getProperty"secretKey";
catch IOException e
e printStackTrace;
public String generatePolicyString awsidString awskey
return DEFAULT_AMAZON_POLICY;
public String signPolicyString awskeyString policy
try
return Signature calculateRFC2104HMAC policy awskey;
catch SignatureException e
e printStackTrace;
return "error_signing_policy";
public String b64EncodePolicyString policy
//policy = policy.replaceAll("\n", ""); #this breaks it for some unknown reason
policy = policy replaceAll"\r""";
return Encoding EncodeBase64 policy getBytes;
public String readJsonFileString policyFile
InputStream inputStream = PolicyGeneratorclass getClassLoader
getResourceAsStream policyFile;
byte bytes = null;
try
bytes = inputStream available;
inputStream read bytes;
catch IOException e
e printStackTrace;
return bytes;
As a test HTTP client we'll be using curl driven by ruby, its a pretty simple script you just have to set all the right curl flags and also worry about the order as amazon services are picky about that.
# this test will hit a server and then using the response upload a file to s3.
#
server = "http://192.168.254.6"
port = "8080"
facebook_user = "malcruzito"
filename= "test.mp3" #assumes this file exists in the directory you run the script from
#hit the server to get the permissions to upload
resp = `curl -H Accept:application/json " : /proj/policysignatures/service?facebook_id= &filename= "`
parsed = JSON.parse(resp)
#puts parsed
#upload the file
curl_command = "curl -L -v -b cookiejar.txt -c cookiejar.txt "
curl_command += " -F \"policy=\""
curl_command += " -F \"acl=\""
curl_command += " -F \"redirect=\""
curl_command += " -F \"signature=\""
curl_command += " -F \"AWSAccessKeyId=\""
curl_command += " -F \"bucket=\""
curl_command += " -F \"key=\""
curl_command += " -F \"content-type=\""
curl_command += " -F \"file=\""
curl_command += " "
print curl_command +"\n"
result = ``
p result
No comments:
Post a Comment