forked from lifuzu/react-native-uploader-s3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
s3_policy.js
127 lines (108 loc) · 3.48 KB
/
s3_policy.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
* Module dependencies.
*/
var crypto = require("crypto-js");
var Buffer = global.Buffer || require('buffer').Buffer;
/**
* Create an s3 policy and signature via `opts`:
*
* - `acl` acl such as "public-read"
* - `expires` expiration date
* - `key` s3 access id
* - `secret` s3 secret
* - `bucket` bucket name
* - `path` restrict object name to prefix [""]
* - `type` restrict content-type prefix [""]
* - `service` default 's3'
* - `date` now, format 'YYYYMMDD'
* - `length` max size restriction
* - `conditions` an optional Array of custom "conditions" to include in the policy
*
* An object with `.signature` and `.policy` is returned.
*
* @param {Object} opts
* @return {Object}
* @api public
*/
module.exports = function(opts){
var ret = {};
if (!Array.isArray(opts.conditions)) opts.conditions = [];
opts.conditions.push(['starts-with', '$key', opts.path || '']);
opts.conditions.push({'success_action_status': '201'});
opts.conditions.push(['starts-with', '$Content-Type', opts.type || '']);
// opts.conditions.push(['starts-with', '$Content-Length', '']);
opts.conditions.push({'x-amz-meta-uuid': "14365123651274"});
// opts.conditions.push({'x-amz-server-side-encryption': "AES256"});
// opts.conditions.push(["starts-with", "$x-amz-meta-tag", ""]);
let date = opts.date || (new Date()).toISOString().slice(0,10).replace(/-/g,"");
let service = opts.service || 's3';
let credential = opts.key + "/" + date + "/" + opts.region + "/" + service +"/aws4_request";
opts.conditions.push({'x-amz-credential': credential});
opts.conditions.push({'x-amz-algorithm': "AWS4-HMAC-SHA256"});
opts.conditions.push({'x-amz-date': date + "T000000Z"});
if (opts.length) {
opts.conditions.push(['content-length-range', 1, opts.length]);
}
ret.date = date;
ret.credential = credential;
ret.policy = policy(opts);
let signatureKey = getSignatureKey(opts.secret, date, opts.region, service);
ret.signature = signature(ret.policy, signatureKey);
return ret;
};
/**
* Create an s3 policy via `opts`.
*
* @param {Object} opts
* @return {String}
* @api public
*/
function policy(opts) {
if (!opts) throw new Error('settings required');
if (!opts.expires) throw new Error('.expires required');
if (!opts.bucket) throw new Error('.bucket required');
if (!opts.acl) throw new Error('.acl required');
var conds = opts.conditions || [];
conds.push({ bucket: opts.bucket });
conds.push({ acl: opts.acl });
var data = {
// ISO format: "2015-12-30T12:00:00.000Z",
expiration: opts.expires.toISOString(),
conditions: conds
};
var json = JSON.stringify(data, "utf-8");
// console.log(json);
var base = new Buffer(json).toString('base64');
return base;
}
/**
* Create signature key.
*
* @param {String} key
* @param {String} date
* @param {String} region
* @param {String} service
* @return {String}
* @api private
*/
function getSignatureKey(key, date, region, service = 's3') {
let _date = crypto.HmacSHA256(date, "AWS4" + key);
let _region = crypto.HmacSHA256(region, _date);
let _service = crypto.HmacSHA256(service, _region);
let _signing = crypto.HmacSHA256("aws4_request", _service);
return _signing;
}
/**
* HMAC SHA256 of the policy / secret.
*
* @param {String} policy
* @param {String} secret
* @return {String}
* @api private
*/
function signature(policy, secret) {
if (!secret) throw new Error('secret required');
return crypto
.HmacSHA256(policy, secret)
.toString(crypto.enc.Hex);
}