git-off

git off handles large files in git repos
git clone https://noulin.net/git/git-off.git
Log | Files | Refs | README

signer.js (7217B)


      1 var AWS = require('../core'),
      2     url = AWS.util.url,
      3     crypto = AWS.util.crypto.lib,
      4     base64Encode = AWS.util.base64.encode,
      5     inherit = AWS.util.inherit;
      6 
      7 var queryEncode = function (string) {
      8     var replacements = {
      9         '+': '-',
     10         '=': '_',
     11         '/': '~'
     12     };
     13     return string.replace(/[\+=\/]/g, function (match) {
     14         return replacements[match];
     15     });
     16 };
     17 
     18 var signPolicy = function (policy, privateKey) {
     19     var sign = crypto.createSign('RSA-SHA1');
     20     sign.write(policy);
     21     return queryEncode(sign.sign(privateKey, 'base64'))
     22 };
     23 
     24 var signWithCannedPolicy = function (url, expires, keyPairId, privateKey) {
     25     var policy = JSON.stringify({
     26         Statement: [
     27             {
     28                 Resource: url,
     29                 Condition: { DateLessThan: { 'AWS:EpochTime': expires } }
     30             }
     31         ]
     32     });
     33 
     34     return {
     35         Expires: expires,
     36         'Key-Pair-Id': keyPairId,
     37         Signature: signPolicy(policy.toString(), privateKey)
     38     };
     39 };
     40 
     41 var signWithCustomPolicy = function (policy, keyPairId, privateKey) {
     42     policy = policy.replace(/\s/mg, policy);
     43 
     44     return {
     45         Policy: queryEncode(base64Encode(policy)),
     46         'Key-Pair-Id': keyPairId,
     47         Signature: signPolicy(policy, privateKey)
     48     }
     49 };
     50 
     51 var determineScheme = function (url) {
     52     var parts = url.split('://');
     53     if (parts.length < 2) {
     54         throw new Error('Invalid URL.');
     55     }
     56 
     57     return parts[0].replace('*', '');
     58 };
     59 
     60 var getRtmpUrl = function (rtmpUrl) {
     61     var parsed = url.parse(rtmpUrl);
     62     return parsed.path.replace(/^\//, '') + (parsed.hash || '');
     63 };
     64 
     65 var getResource = function (url) {
     66     switch (determineScheme(url)) {
     67         case 'http':
     68         case 'https':
     69             return url;
     70         case 'rtmp':
     71             return getRtmpUrl(url);
     72         default:
     73             throw new Error('Invalid URI scheme. Scheme must be one of'
     74                 + ' http, https, or rtmp');
     75     }
     76 };
     77 
     78 var handleError = function (err, callback) {
     79     if (!callback || typeof callback !== 'function') {
     80         throw err;
     81     }
     82 
     83     callback(err);
     84 };
     85 
     86 var handleSuccess = function (result, callback) {
     87     if (!callback || typeof callback !== 'function') {
     88         return result;
     89     }
     90 
     91     callback(null, result);
     92 };
     93 
     94 AWS.CloudFront.Signer = inherit({
     95     /**
     96      * A signer object can be used to generate signed URLs and cookies for granting
     97      * access to content on restricted CloudFront distributions.
     98      *
     99      * @see http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html
    100      *
    101      * @param keyPairId [String]    (Required) The ID of the CloudFront key pair
    102      *                              being used.
    103      * @param privateKey [String]   (Required) A private key in RSA format.
    104      */
    105     constructor: function Signer(keyPairId, privateKey) {
    106         if (keyPairId === void 0 || privateKey === void 0) {
    107             throw new Error('A key pair ID and private key are required');
    108         }
    109 
    110         this.keyPairId = keyPairId;
    111         this.privateKey = privateKey;
    112     },
    113 
    114     /**
    115      * Create a signed Amazon CloudFront Cookie.
    116      *
    117      * @param options [Object]            The options to create a signed cookie.
    118      * @option options url [String]     The URL to which the signature will grant
    119      *                                  access. Required unless you pass in a full
    120      *                                  policy.
    121      * @option options expires [Number] A Unix UTC timestamp indicating when the
    122      *                                  signature should expire. Required unless you
    123      *                                  pass in a full policy.
    124      * @option options policy [String]  A CloudFront JSON policy. Required unless
    125      *                                  you pass in a url and an expiry time.
    126      *
    127      * @param cb [Function] if a callback is provided, this function will
    128      *   pass the hash as the second parameter (after the error parameter) to
    129      *   the callback function.
    130      *
    131      * @return [Object] if called synchronously (with no callback), returns the
    132      *   signed cookie parameters.
    133      * @return [null] nothing is returned if a callback is provided.
    134      */
    135     getSignedCookie: function (options, cb) {
    136         var signatureHash = 'policy' in options
    137             ? signWithCustomPolicy(options.policy, this.keyPairId, this.privateKey)
    138             : signWithCannedPolicy(options.url, options.expires, this.keyPairId, this.privateKey);
    139 
    140         var cookieHash = {};
    141         for (var key in signatureHash) {
    142             if (Object.prototype.hasOwnProperty.call(signatureHash, key)) {
    143                 cookieHash['CloudFront-' + key] = signatureHash[key];
    144             }
    145         }
    146 
    147         return handleSuccess(cookieHash, cb);
    148     },
    149 
    150     /**
    151      * Create a signed Amazon CloudFront URL.
    152      *
    153      * Keep in mind that URLs meant for use in media/flash players may have
    154      * different requirements for URL formats (e.g. some require that the
    155      * extension be removed, some require the file name to be prefixed
    156      * - mp4:<path>, some require you to add "/cfx/st" into your URL).
    157      *
    158      * @param options [Object]          The options to create a signed URL.
    159      * @option options url [String]     The URL to which the signature will grant
    160      *                                  access. Required.
    161      * @option options expires [Number] A Unix UTC timestamp indicating when the
    162      *                                  signature should expire. Required unless you
    163      *                                  pass in a full policy.
    164      * @option options policy [String]  A CloudFront JSON policy. Required unless
    165      *                                  you pass in a url and an expiry time.
    166      *
    167      * @param cb [Function] if a callback is provided, this function will
    168      *   pass the URL as the second parameter (after the error parameter) to
    169      *   the callback function.
    170      *
    171      * @return [String] if called synchronously (with no callback), returns the
    172      *   signed URL.
    173      * @return [null] nothing is returned if a callback is provided.
    174      */
    175     getSignedUrl: function (options, cb) {
    176         try {
    177             var resource = getResource(options.url);
    178         } catch (err) {
    179             return handleError(err, cb);
    180         }
    181 
    182         var parsedUrl = url.parse(options.url, true),
    183             signatureHash = Object.prototype.hasOwnProperty.call(options, 'policy')
    184                 ? signWithCustomPolicy(options.policy, this.keyPairId, this.privateKey)
    185                 : signWithCannedPolicy(resource, options.expires, this.keyPairId, this.privateKey);
    186 
    187         parsedUrl.search = null;
    188         for (var key in signatureHash) {
    189             if (Object.prototype.hasOwnProperty.call(signatureHash, key)) {
    190                 parsedUrl.query[key] = signatureHash[key];
    191             }
    192         }
    193 
    194         try {
    195             var signedUrl = determineScheme(options.url) === 'rtmp'
    196                     ? getRtmpUrl(url.format(parsedUrl))
    197                     : url.format(parsedUrl);
    198         } catch (err) {
    199             return handleError(err, cb);
    200         }
    201 
    202         return handleSuccess(signedUrl, cb);
    203     }
    204 });
    205 
    206 module.exports = AWS.CloudFront.Signer;