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=20971520Next 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 myawsconsoleprojweb;
2
3 import javatextSimpleDateFormat;
4 import javautilDate;
5 import javautilTimeZone;
6
7 import javaxmanagementtimerTimer;
8 import javaxservlethttpHttpServletRequest;
9
10 import myawsconsoleprojdomainPolicySignature;
11 import myawsconsoleprojtoolingPolicyGenerator;
12
13 import orgapachelog4jLogger;
14 import orgspringframeworkrooaddonwebmvccontrollerRooWebScaffold;
15 import orgspringframeworkstereotypeController;
16 import orgspringframeworkwebbindannotationRequestMapping;
17 import orgspringframeworkwebbindannotationRequestMethod;
18 import orgspringframeworkwebbindannotationRequestParam;
19 import orgspringframeworkwebbindannotationResponseBody;
20
21
22 @RooWebScaffoldpath = "policysignatures"formBackingObject = PolicySignatureclassupdate = falsedelete = falsecreate = false
23 @RequestMapping"/policysignatures"
24 @Controller
25 public class PolicySignatureService
26
27 private static Logger logger = LoggergetLoggerPolicySignatureServiceclass;
28
29
30 @RequestMappingvalue = "/service"method = RequestMethodGETheaders = "Accept=application/json"
31 @ResponseBody
32 public Object showJson@RequestParamvalue = "facebook_id"required = true String facebook_id
33 @RequestParamvalue = "filename"required = true String filename
34 HttpServletRequest request
35 PolicyGenerator generator = ;
36 String formattedExpirationDate = getFormattedExpirationDate;
37 String generatedPolicy = makeAWSPostPolicyfacebook_idfilenamegeneratorformattedExpirationDate;
38 String b64EncodedPolicy = generatorb64EncodePolicygeneratedPolicy;
39 String signature = generatorsignPolicygeneratorAWSSECRETKEYb64EncodedPolicy;
40 PolicySignature policysignature = makePolicySignaturefacebook_id
41 filenamegeneratorb64EncodedPolicysignature;
42 logger.inforequestgetRemoteAddr+","+ generatedPolicy +","+ policysignaturetoJson;
43 return policysignaturetoJson;
44
45
46
47 public PolicySignature makePolicySignatureString facebook_id
48 String filenamePolicyGenerator generatorString b64EncodedPolicy
49 String signature
50 PolicySignature policysignature = ;
51 policysignaturesetPolicyb64EncodedPolicy;
52 policysignaturesetSignaturesignature;
53 policysignaturesetAWSAccessKeyIdgeneratorAWSKEYID;
54 policysignaturesetBucketgeneratorBUCKET;
55 policysignaturesetFkeygeneratorUPLOADDIR+"/"+facebook_id+"/"+filename;
56 policysignaturesetContent_typegeneratorCONTENT_TYPE;
57 policysignaturesetFile"@" + filename;
58 policysignaturesetS3urlgeneratorS3URL + "/" + generatorBUCKET;
59 policysignaturesetRedirectgeneratorS3URL + "/" + generatorBUCKET + "/" + generatorUPLOADDIR + "/" + facebook_id + "/" + filename;
60 policysignaturesetAclgeneratorACL;
61 return policysignature;
62
63
64
65 public String makeAWSPostPolicyString facebook_idString filename
66 PolicyGenerator generatorString formattedExpirationDate
67 String generatedPolicy = generatorgeneratePolicygeneratorAWSKEYIDgeneratorAWSSECRETKEY;
68 generatedPolicy = generatedPolicyreplaceAll"repl_expiration"formattedExpirationDate;
69 generatedPolicy = generatedPolicyreplaceAll"repl_bucket"generatorBUCKET;
70 generatedPolicy = generatedPolicyreplaceAll"repl_acl"generatorACL;
71 generatedPolicy = generatedPolicyreplaceAll"repl_filename"filename;
72 generatedPolicy = generatedPolicyreplaceAll"repl_content_type"generatorCONTENT_TYPE;
73 generatedPolicy = generatedPolicyreplaceAll"repl_max_content_bytes"generatorMAX_CONTENT_BYTES;
74 generatedPolicy = generatedPolicyreplaceAll"repl_foldername"generatorUPLOADDIR;
75 generatedPolicy = generatedPolicyreplaceAll"repl_username"facebook_id;
76 generatedPolicy = generatedPolicyreplaceAll"repl_s3url"generatorS3URL;
77 generatedPolicy = generatedPolicyreplaceAll"\r""";
78 generatedPolicy = generatedPolicyreplaceAll"\n""";
79 return generatedPolicy;
80
81
82
83 public String getFormattedExpirationDate
84 Date now = ;
85 Date oneHourFromNow = nowgetTime + TimerONE_HOUR;
86 TimeZone tz = TimeZonegetTimeZone "UTC" ;
87 SimpleDateFormat dfm = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
88 dfmsetTimeZone tz ;
89 String formattedExpirationDate = dfmformatoneHourFromNow;
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 myawsconsoleprojtooling;
import javaioIOException;
import javaioInputStream;
import javasecuritySignatureException;
import javautilProperties;
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 = PolicyGeneratorclassgetClassLoadergetResourceAsStream"permissive.json";
InputStream bucketingInputStream = PolicyGeneratorclassgetClassLoadergetResourceAsStream"amazon_bucketing.properties";
InputStream credentialsInputStream = PolicyGeneratorclassgetClassLoadergetResourceAsStream"AwsCredentials.properties";
byte bytes = null;
try
bytes = policyInputStreamavailable;
policyInputStreamreadbytes;
DEFAULT_AMAZON_POLICY = bytes;
Properties awsprops = ;
awspropsloadbucketingInputStream;
BUCKET = awspropsgetProperty"BUCKET";
UPLOADDIR = awspropsgetProperty"UPLOADDIR";
CONTENT_TYPE = awspropsgetProperty"CONTENT_TYPE";
S3URL = awspropsgetProperty"S3URL";
ACL = awspropsgetProperty"ACL";
MAX_CONTENT_BYTES = awspropsgetProperty"MAX_CONTENT_BYTES";
Properties awscreds = ;
awscredsloadcredentialsInputStream;
AWSKEYID = awscredsgetProperty"accessKey";
AWSSECRETKEY = awscredsgetProperty"secretKey";
catch IOException e
eprintStackTrace;
public String generatePolicyString awsidString awskey
return DEFAULT_AMAZON_POLICY;
public String signPolicyString awskeyString policy
try
return SignaturecalculateRFC2104HMACpolicyawskey;
catch SignatureException e
eprintStackTrace;
return "error_signing_policy";
public String b64EncodePolicyString policy
//policy = policy.replaceAll("\n", ""); #this breaks it for some unknown reason
policy = policyreplaceAll"\r""";
return EncodingEncodeBase64policygetBytes;
public String readJsonFileString policyFile
InputStream inputStream = PolicyGeneratorclassgetClassLoader
getResourceAsStreampolicyFile;
byte bytes = null;
try
bytes = inputStreamavailable;
inputStreamreadbytes;
catch IOException e
eprintStackTrace;
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