├── .gitignore ├── .npmignore ├── History.md ├── Makefile ├── Readme.md ├── example.js ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | support 2 | test 3 | examples 4 | *.sock 5 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 0.2.0 / 2014-01-10 3 | ================== 4 | 5 | * add a `conditions` option for custom conditions 6 | 7 | 0.0.1 / 2010-01-03 8 | ================== 9 | 10 | * Initial release 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | test: 3 | @./node_modules/.bin/mocha \ 4 | --require should \ 5 | --reporter spec 6 | 7 | .PHONY: test -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | 2 | # s3-policy 3 | 4 | [S3 policy][] generation for client-side uploads. By default, `Content-Type` and 5 | `Content-Length` form fields are __required__, but can contain any value. 6 | 7 | ## Options 8 | 9 | Create an s3 policy and signature via `opts`: 10 | 11 | - `acl` acl such as "public-read" 12 | - `expires` expiration date 13 | - `secret` s3 secret 14 | - `bucket` bucket name 15 | - `key` access key 16 | - `name` restrict key to prefix [""] 17 | - `type` restrict content-type prefix [""] 18 | - `length` max size restriction 19 | - `conditions` an optional Array of custom "conditions" to include in the policy 20 | 21 | An object with `.signature` and `.policy` is returned. 22 | 23 | ## Example 24 | 25 | ```js 26 | var policy = require('s3-policy'); 27 | 28 | var p = policy({ 29 | secret: 'something', 30 | length: 5000000, 31 | bucket: 'i.cloudup.com', 32 | key: 'asdfasdfaewrw', 33 | expires: new Date(Date.now() + 60000), 34 | acl: 'public-read' 35 | }); 36 | 37 | console.log(p.policy); 38 | console.log(p.signature); 39 | ``` 40 | 41 | ## License 42 | 43 | (The MIT License) 44 | 45 | Copyright (c) 2013 TJ Holowaychuk <tj@vision-media.ca> 46 | 47 | Permission is hereby granted, free of charge, to any person obtaining 48 | a copy of this software and associated documentation files (the 49 | 'Software'), to deal in the Software without restriction, including 50 | without limitation the rights to use, copy, modify, merge, publish, 51 | distribute, sublicense, and/or sell copies of the Software, and to 52 | permit persons to whom the Software is furnished to do so, subject to 53 | the following conditions: 54 | 55 | The above copyright notice and this permission notice shall be 56 | included in all copies or substantial portions of the Software. 57 | 58 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 59 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 60 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 61 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 62 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 63 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 64 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 65 | 66 | [S3 policy]: http://docs.aws.amazon.com/AmazonS3/latest/dev/HTTPPOSTForms.html#HTTPPOSTConstructPolicy 67 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | 2 | var policy = require('./'); 3 | 4 | var p = policy({ 5 | secret: 'something', 6 | length: 5000000, 7 | bucket: 'i.cloudup.com', 8 | key: 'asdfasdfaewrw', 9 | expires: new Date(Date.now() + 60000), 10 | acl: 'public-read' 11 | }); 12 | 13 | console.log(p.policy); 14 | console.log(p.signature); -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var crypto = require('crypto'); 7 | 8 | /** 9 | * Create an s3 policy and signature via `opts`: 10 | * 11 | * - `acl` acl such as "public-read" 12 | * - `expires` expiration date 13 | * - `secret` s3 secret 14 | * - `bucket` bucket name 15 | * - `name` restrict object name to prefix [""] 16 | * - `type` restrict content-type prefix [""] 17 | * - `length` max size restriction 18 | * - `conditions` an optional Array of custom "conditions" to include in the policy 19 | * 20 | * An object with `.signature` and `.policy` is returned. 21 | * 22 | * @param {Object} opts 23 | * @return {Object} 24 | * @api public 25 | */ 26 | 27 | module.exports = function(opts){ 28 | var ret = {}; 29 | 30 | if (!Array.isArray(opts.conditions)) opts.conditions = []; 31 | opts.conditions.push(['starts-with', '$key', opts.name || '']); 32 | opts.conditions.push(['starts-with', '$Content-Type', opts.type || '']); 33 | opts.conditions.push(['starts-with', '$Content-Length', '']); 34 | 35 | if (opts.length) { 36 | opts.conditions.push(['content-length-range', 1, opts.length]); 37 | } 38 | 39 | ret.policy = policy(opts); 40 | ret.signature = signature(ret.policy, opts.secret); 41 | 42 | return ret; 43 | }; 44 | 45 | /** 46 | * Create an s3 policy via `opts`. 47 | * 48 | * @param {Object} opts 49 | * @return {String} 50 | * @api public 51 | */ 52 | 53 | function policy(opts) { 54 | if (!opts) throw new Error('settings required'); 55 | if (!opts.expires) throw new Error('.expires required'); 56 | if (!opts.bucket) throw new Error('.bucket required'); 57 | if (!opts.acl) throw new Error('.acl required'); 58 | 59 | var conds = opts.conditions || []; 60 | conds.push({ bucket: opts.bucket }); 61 | conds.push({ acl: opts.acl }); 62 | 63 | var data = { 64 | expiration: opts.expires.toISOString(), 65 | conditions: conds 66 | }; 67 | 68 | var json = JSON.stringify(data); 69 | var base = new Buffer(json).toString('base64'); 70 | return base; 71 | } 72 | 73 | /** 74 | * SHA1 of the policy / secret. 75 | * 76 | * @param {String} policy 77 | * @param {String} secret 78 | * @return {String} 79 | * @api private 80 | */ 81 | 82 | function signature(policy, secret) { 83 | if (!secret) throw new Error('secret required'); 84 | 85 | return crypto 86 | .createHmac('sha1', secret) 87 | .update(policy) 88 | .digest('base64'); 89 | } 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "s3-policy", 3 | "version": "0.2.0", 4 | "description": "S3 policy generation for client-side uploads", 5 | "keywords": ["s3", "policy"], 6 | "author": "TJ Holowaychuk ", 7 | "repository": "visionmedia/node-s3-policy", 8 | "dependencies": {}, 9 | "devDependencies": { 10 | "mocha": "*", 11 | "should": "*" 12 | }, 13 | "main": "index", 14 | "files": ["index.js"] 15 | } 16 | --------------------------------------------------------------------------------