UNPKG

azure-storage-legacy

Version:

Microsoft Azure Storage Client Library for node for back compat with older versions of node sdk

193 lines (162 loc) 7.99 kB
// // Copyright (c) Microsoft and contributors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // limitations under the License. // // Module dependencies. var qs = require('querystring'); var azureCommon = require('azure-common'); var azureutil = azureCommon.util; var HmacSha256Sign = azureCommon.HmacSha256Sign; var Constants = azureCommon.Constants; var BlobConstants = Constants.BlobConstants; var QueryStringConstants = Constants.QueryStringConstants; var SAS_VERSION = '2012-02-12'; /** * Creates a new SharedAccessSignature object. * * @constructor * @param {string} storageAccount The storage account. * @param {string} storageAccessKey The storage account's access key. * @param {array} permissionSet An array of URL's for which there is a permission defined. */ function SharedAccessSignature(storageAccount, storageAccessKey, permissionSet) { this.storageAccount = storageAccount; this.storageAccessKey = storageAccessKey; this.permissionSet = permissionSet; this.signer = new HmacSha256Sign(storageAccessKey); } /** * Generates the query string for a shared access signature signing. * * @this {SharedAccessSignature} * @param {string} path The path to the resource. * @parma {ResourceTypes} resourceType The resource type. * @param {object} sharedAccessPolicy The shared access policy. * @param {string} [sharedAccessPolicy.Id] The signed identifier. * @param {SharedAccessPermissions} sharedAccessPolicy.AccessPolicy.Permissions The permission type. * @param {date} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid. * @param {date} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired. * @return {object} The shared access signature query string. */ SharedAccessSignature.prototype.generateSignedQueryString = function (path, queryString, resourceType, sharedAccessPolicy) { if (sharedAccessPolicy.AccessPolicy) { if (sharedAccessPolicy.AccessPolicy.Start) { queryString[QueryStringConstants.SIGNED_START] = sharedAccessPolicy.AccessPolicy.Start; } if (sharedAccessPolicy.AccessPolicy.Expiry) { queryString[QueryStringConstants.SIGNED_EXPIRY] = sharedAccessPolicy.AccessPolicy.Expiry; } if (sharedAccessPolicy.AccessPolicy.Permissions) { queryString[QueryStringConstants.SIGNED_PERMISSIONS] = sharedAccessPolicy.AccessPolicy.Permissions; } } queryString[QueryStringConstants.SIGNED_RESOURCE] = resourceType; if (sharedAccessPolicy.Id) { queryString[QueryStringConstants.SIGNED_IDENTIFIER] = sharedAccessPolicy.Id; } queryString[QueryStringConstants.SIGNED_VERSION] = SAS_VERSION; queryString[QueryStringConstants.SIGNATURE] = this._generateSignature(path, resourceType, sharedAccessPolicy); return queryString; }; /** * Signs a request with the signature header. * * @this {SharedAccessSignature} * @param {WebResource} The webresource to be signed. * @param {function(error)} callback The callback function. * @return {undefined} */ SharedAccessSignature.prototype.signRequest = function (webResource, callback) { var self = this; for (var permission in this.permissionSet) { if (this.permissionSet.hasOwnProperty(permission)) { var sharedAccessSignature = this.permissionSet[permission]; if (self._permissionMatchesRequest(sharedAccessSignature, webResource, webResource.properties[BlobConstants.ResourceTypeProperty], webResource.properties[BlobConstants.SharedAccessPermissionProperty])) { if (webResource.uri.indexOf('?') === -1) { webResource.uri += '?'; } else { webResource.uri += '&'; } webResource.uri += qs.stringify(sharedAccessSignature.queryString); break; } } } callback(null); }; /** * Generates the shared access signature for a resource. * * @this {SharedAccessSignature} * @param {string} path The path to the resource. * @parma {ResourceTypes} resourceType The resource type. * @param {object} sharedAccessPolicy The shared access policy. * @param {string} [sharedAccessPolicy.Id] The signed identifier. * @param {SharedAccessPermissions} sharedAccessPolicy.AccessPolicy.Permissions The permission type. * @param {date} [sharedAccessPolicy.AccessPolicy.Start] The time at which the Shared Access Signature becomes valid. * @param {date} sharedAccessPolicy.AccessPolicy.Expiry The time at which the Shared Access Signature becomes expired. * @return {string} The shared access signature. */ SharedAccessSignature.prototype._generateSignature = function (path, resourceType, sharedAccessPolicy) { var getvalueToAppend = function (value, noNewLine) { var returnValue = ''; if (!azureutil.objectIsNull(value)) { returnValue = value; } if (noNewLine !== true) { returnValue += '\n'; } return returnValue; }; // Add leading slash to path if (path.substr(0, 1) !== '/') { path = '/' + path; } var canonicalizedResource = '/' + this.storageAccount + path; var stringToSign = getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Permissions : '') + getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Start : '') + getvalueToAppend(sharedAccessPolicy.AccessPolicy ? sharedAccessPolicy.AccessPolicy.Expiry : '') + getvalueToAppend(canonicalizedResource) + getvalueToAppend(sharedAccessPolicy.Id) + SAS_VERSION; return this.signer.sign(stringToSign); }; /** * Generates the query string for a shared access signature signing. * * @this {SharedAccessSignature} * @param {object} sharedAccessSignature The shared access signature object. * @parma {WebResource} webResource The web resource. * @parma {ResourceTypes} resourceType The resource type. * @param {SharedAccessPermissions} requiredPermission The time at which the Shared Access Signature becomes valid. * @return {bool} true if the request matches the permission set; false otherwise. */ SharedAccessSignature.prototype._permissionMatchesRequest = function (sharedAccessSignature, webResource, resourceType, requiredPermission) { var requiredResourceType = resourceType; if (requiredResourceType === BlobConstants.ResourceTypes.BLOB) { requiredResourceType += BlobConstants.ResourceTypes.CONTAINER; } for (var property in sharedAccessSignature.queryString) { if (property === QueryStringConstants.SIGNED_RESOURCE && requiredResourceType.indexOf(sharedAccessSignature.queryString[property]) === -1) { return false; } else if (property === QueryStringConstants.SIGNED_PERMISSIONS && requiredPermission.indexOf(sharedAccessSignature.queryString[property]) === -1) { return false; } } return webResource.path.indexOf(sharedAccessSignature.path) !== -1; }; module.exports = SharedAccessSignature;