/// <summary>
        /// Parse Uri for SAS (Shared access signature) information.
        /// </summary>
        /// <param name="address">The complete Uri.</param>
        /// <param name="parsedCredentials">The credentials to use.</param>
        /// <remarks>
        /// Validate that no other query parameters are passed in.
        /// Any SAS information will be recorded as corresponding credentials instance.
        /// If credentials is passed in and it does not match the SAS information found, an
        /// exception will be thrown.
        /// Otherwise a new client is created based on SAS information or as anonymous credentials.
        /// </remarks>
        internal static Uri ParseBlobQueryAndVerify(Uri address, out StorageCredentials parsedCredentials, out DateTimeOffset?parsedSnapshot)
        {
            CommonUtils.AssertNotNull("address", address);
            if (!address.IsAbsoluteUri)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.RelativeAddressNotPermitted, address.ToString());
                throw new ArgumentException(errorMessage, "address");
            }

            IDictionary <string, string> queryParameters = HttpUtility.ParseQueryString(address.Query);

            parsedSnapshot = null;
            string snapshot;

            if (queryParameters.TryGetValue(Constants.QueryConstants.Snapshot, out snapshot))
            {
                if (!string.IsNullOrEmpty(snapshot))
                {
                    parsedSnapshot = ParseSnapshotTime(snapshot);
                }
            }

            parsedCredentials = SharedAccessSignatureHelper.ParseQuery(queryParameters);
            return(new Uri(address.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)));
        }
        public string GetSharedAccessSignature(SharedAccessQueuePolicy policy, string accessPolicyIdentifier, string sasVersion)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            validatedSASVersion = SharedAccessSignatureHelper.ValidateSASVersionString(sasVersion);
            string            resourceName        = this.GetCanonicalName(validatedSASVersion);
            StorageAccountKey accountKey          = this.ServiceClient.Credentials.Key;

            string signature = SharedAccessSignatureHelper.GetHash(
                policy,
                accessPolicyIdentifier,
                resourceName,
                validatedSASVersion,
                accountKey.KeyValue);

            string accountKeyName = accountKey.KeyName;

            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSignature(
                policy,
                accessPolicyIdentifier,
                signature,
                accountKeyName,
                validatedSASVersion);

            return(builder.ToString());
        }
        /// <summary>
        /// Returns a shared access signature for the share.
        /// </summary>
        /// <param name="policy">A <see cref="SharedAccessFilePolicy"/> object specifying the access policy for the shared access signature.</param>
        /// <param name="groupPolicyIdentifier">A share-level access policy.</param>
        /// <param name="protocols">The allowed protocols (https only, or http and https). Null if you don't want to restrict protocol.</param>
        /// <param name="ipAddressOrRange">The allowed IP address or IP address range. Null if you don't want to restrict based on IP address.</param>
        /// <returns>A shared access signature, as a URI query string.</returns>
        /// <remarks>The query string returned includes the leading question mark.</remarks>
        public string GetSharedAccessSignature(SharedAccessFilePolicy policy, string groupPolicyIdentifier, SharedAccessProtocol?protocols, IPAddressOrRange ipAddressOrRange)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            resourceName = this.GetSharedAccessCanonicalName();
            StorageAccountKey accountKey   = this.ServiceClient.Credentials.Key;

#if ALL_SERVICES
            string signature = SharedAccessSignatureHelper.GetHash(policy, null /* headers */, groupPolicyIdentifier, resourceName, OperationContext.StorageVersion ?? Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange, accountKey.KeyValue);
#else
            string signature = FileSharedAccessSignatureHelper.GetHash(policy, null /* headers */, groupPolicyIdentifier, resourceName, Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange, accountKey.KeyValue);
#endif
            string accountKeyName = accountKey.KeyName;
#if ALL_SERVICES
            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSignature(policy, null /* headers */, groupPolicyIdentifier, "s", signature, accountKeyName, OperationContext.StorageVersion ?? Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange);
#else
            UriQueryBuilder builder = FileSharedAccessSignatureHelper.GetSignature(policy, null /* headers */, groupPolicyIdentifier, "s", signature, accountKeyName, Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange);
#endif

            return(builder.ToString());
        }
        /// <summary>
        /// Returns a shared access signature for the queue.
        /// </summary>
        /// <param name="policy">A <see cref="SharedAccessQueuePolicy"/> object specifying the access policy for the shared access signature.</param>
        /// <param name="accessPolicyIdentifier">A string identifying a stored access policy.</param>
        /// <param name="protocols">The allowed protocols (https only, or http and https). Null if you don't want to restrict protocol.</param>
        /// <param name="ipAddressOrRange">The allowed IP address or IP address range. Null if you don't want to restrict based on IP address.</param>
        /// <returns>A shared access signature, as a URI query string.</returns>
        /// <remarks>The query string returned includes the leading question mark.</remarks>
        public string GetSharedAccessSignature(SharedAccessQueuePolicy policy, string accessPolicyIdentifier, SharedAccessProtocol?protocols, IPAddressOrRange ipAddressOrRange)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            resourceName = this.GetCanonicalName();
            StorageAccountKey accountKey   = this.ServiceClient.Credentials.Key;

            string signature = SharedAccessSignatureHelper.GetHash(
                policy,
                accessPolicyIdentifier,
                resourceName,
                Constants.HeaderConstants.TargetStorageVersion,
                protocols,
                ipAddressOrRange,
                accountKey.KeyValue);

            string accountKeyName = accountKey.KeyName;

            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSignature(
                policy,
                accessPolicyIdentifier,
                signature,
                accountKeyName,
                Constants.HeaderConstants.TargetStorageVersion,
                protocols,
                ipAddressOrRange);

            return(builder.ToString());
        }
        /// <summary>
        /// Returns a shared access signature for the queue.
        /// </summary>
        /// <param name="policy">The access policy for the shared access signature.</param>
        /// <param name="accessPolicyIdentifier">A queue-level access policy.</param>
        /// <returns>A shared access signature.</returns>
        public string GetSharedAccessSignature(SharedAccessQueuePolicy policy, string accessPolicyIdentifier)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string resourceName = this.GetCanonicalName();

            string signature = SharedAccessSignatureHelper.GetSharedAccessSignatureHashImpl(
                policy,
                accessPolicyIdentifier,
                resourceName,
                this.ServiceClient.Credentials);

            string accountKeyName = this.ServiceClient.Credentials.IsSharedKey ? this.ServiceClient.Credentials.KeyName : null;

            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSharedAccessSignatureImpl(
                policy,
                accessPolicyIdentifier,
                signature,
                accountKeyName);

            return(builder.ToString());
        }
Esempio n. 6
0
        /// <summary>
        /// Parse Uri for SAS (Shared access signature) information.
        /// </summary>
        /// <param name="address">The complete Uri.</param>
        /// <param name="parsedCredentials">The credentials to use.</param>
        /// <returns>The file URI without credentials info</returns>
        /// <exception cref="System.ArgumentException">address</exception>
        /// <remarks>
        /// Validate that no other query parameters are passed in.
        /// Any SAS information will be recorded as corresponding credentials instance.
        /// If credentials is passed in and it does not match the SAS information found, an
        /// exception will be thrown.
        /// Otherwise a new client is created based on SAS information or as anonymous credentials.
        /// </remarks>
        private static Uri ParseFileQueryAndVerify(Uri address, out StorageCredentials parsedCredentials)
        {
            parsedCredentials = null;
            if (address == null)
            {
                return(null);
            }

            if (!address.IsAbsoluteUri)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.RelativeAddressNotPermitted, address.ToString());
                throw new ArgumentException(errorMessage, "address");
            }

            IDictionary <string, string> queryParameters = HttpWebUtility.ParseQueryString(address.Query);

            parsedCredentials = SharedAccessSignatureHelper.ParseQuery(queryParameters);

            // SAS credentials were passed in the Uri if parsedCredentials is non null.
            if (parsedCredentials != null)
            {
                string signedResource;
                queryParameters.TryGetValue(Constants.QueryConstants.SignedResource, out signedResource);

                if (string.IsNullOrEmpty(signedResource))
                {
                    string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.MissingMandatoryParametersForSAS);
                    throw new ArgumentException(errorMessage);
                }
            }

            return(new Uri(address.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)));
        }
        /// <summary>
        /// Returns a shared access signature for the blob.
        /// </summary>
        /// <param name="policy">A <see cref="SharedAccessBlobPolicy"/> object specifying the access policy for the shared access signature.</param>
        /// <param name="headers">A <see cref="SharedAccessBlobHeaders"/> object specifying optional header values to set for a blob accessed with this SAS.</param>
        /// <param name="groupPolicyIdentifier">A string identifying a stored access policy.</param>
        /// <param name="protocols">The allowed protocols (https only, or http and https). Null if you don't want to restrict protocol.</param>
        /// <param name="ipAddressOrRange">The allowed IP address or IP address range. Null if you don't want to restrict based on IP address.</param>
        /// <returns>A shared access signature, as a URI query string.</returns>
        public string GetSharedAccessSignature(SharedAccessBlobPolicy policy, SharedAccessBlobHeaders headers, string groupPolicyIdentifier, SharedAccessProtocol?protocols, IPAddressOrRange ipAddressOrRange)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.InvariantCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            resourceName = this.GetCanonicalName(true /* ignoreSnapshotTime */);
            StorageAccountKey accountKey   = this.ServiceClient.Credentials.Key;

#if ALL_SERVICES
            string signature = SharedAccessSignatureHelper.GetHash(policy, headers, groupPolicyIdentifier, resourceName, OperationContext.StorageVersion ?? Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange, accountKey.KeyValue);
#else
            string signature = BlobSharedAccessSignatureHelper.GetHash(policy, headers, groupPolicyIdentifier, resourceName, Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange, accountKey.KeyValue);
#endif

            // Future resource type changes from "c" => "container"
#if ALL_SERVICES
            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSignature(policy, headers, groupPolicyIdentifier, "b", signature, accountKey.KeyName, OperationContext.StorageVersion ?? Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange);
#else
            UriQueryBuilder builder = BlobSharedAccessSignatureHelper.GetSignature(policy, headers, groupPolicyIdentifier, "b", signature, accountKey.KeyName, Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange);
#endif

            return(builder.ToString());
        }
Esempio n. 8
0
 private static void WriteSharedAccessIdentifiers(SharedAccessTablePolicies sharedAccessPolicies, Stream outputStream)
 {
     WriteSharedAccessIdentifiers(sharedAccessPolicies, outputStream, delegate(SharedAccessTablePolicy policy, XmlWriter writer)
     {
         writer.WriteElementString("Start", SharedAccessSignatureHelper.GetDateTimeOrEmpty(policy.SharedAccessStartTime));
         writer.WriteElementString("Expiry", SharedAccessSignatureHelper.GetDateTimeOrEmpty(policy.SharedAccessExpiryTime));
         writer.WriteElementString("Permission", SharedAccessTablePolicy.PermissionsToString(policy.Permissions));
     });
 }
Esempio n. 9
0
        ////public string SharedAccessAuthenticatedURI(Uri uri, string permission) { return ""; }

        /// <summary>
        /// Writes a collection of shared access policies to the specified stream in XML format.
        /// </summary>
        /// <param name="sharedAccessPolicies">A collection of shared access policies.</param>
        /// <param name="outputStream">An output stream.</param>
        public static void WriteSharedAccessIdentifiers(SharedAccessPolicies sharedAccessPolicies, Stream outputStream)
        {
            CommonUtils.AssertNotNull("sharedAccessPolicies", sharedAccessPolicies);
            CommonUtils.AssertNotNull("outputStream", outputStream);

            if (sharedAccessPolicies.Count > Constants.MaxSharedAccessPolicyIdentifiers)
            {
                string errorMessage = string.Format(
                    CultureInfo.CurrentCulture,
                    SR.TooManyPolicyIdentifiers,
                    sharedAccessPolicies.Count,
                    Constants.MaxSharedAccessPolicyIdentifiers);

                throw new ArgumentOutOfRangeException("sharedAccessPolicies", errorMessage);
            }

            XmlWriterSettings settings = new XmlWriterSettings();

            settings.Encoding = Encoding.UTF8;

            using (XmlWriter writer = XmlWriter.Create(outputStream, settings))
            {
                writer.WriteStartElement(Constants.SignedIdentifiers);

                foreach (var key in sharedAccessPolicies.Keys)
                {
                    writer.WriteStartElement(Constants.SignedIdentifier);

                    // Set the identifier
                    writer.WriteElementString(Constants.Id, key);

                    // Set the permissions
                    writer.WriteStartElement(Constants.AccessPolicy);

                    var policy = sharedAccessPolicies[key];

                    writer.WriteElementString(
                        Constants.Start,
                        SharedAccessSignatureHelper.GetDateTimeOrEmpty(policy.SharedAccessStartTime));
                    writer.WriteElementString(
                        Constants.Expiry,
                        SharedAccessSignatureHelper.GetDateTimeOrEmpty(policy.SharedAccessExpiryTime));
                    writer.WriteElementString(
                        Constants.Permission,
                        SharedAccessPolicy.PermissionsToString(policy.Permissions));
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                }

                writer.WriteEndDocument();
            }
        }
Esempio n. 10
0
        /// <summary>
        /// Parse Uri for SAS (Shared access signature) information.
        /// </summary>
        /// <param name="address">The complete Uri.</param>
        /// <param name="parsedCredentials">The credentials to use.</param>
        /// <remarks>
        /// Validate that no other query parameters are passed in.
        /// Any SAS information will be recorded as corresponding credentials instance.
        /// If credentials is passed in and it does not match the SAS information found, an
        /// exception will be thrown.
        /// Otherwise a new client is created based on SAS information or as anonymous credentials.
        /// </remarks>
        internal static Uri ParseQueueTableQueryAndVerify(Uri address, out StorageCredentials parsedCredentials)
        {
            CommonUtility.AssertNotNull("address", address);
            if (!address.IsAbsoluteUri)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.RelativeAddressNotPermitted, address.ToString());
                throw new ArgumentException(errorMessage, "address");
            }

            IDictionary <string, string> queryParameters = HttpWebUtility.ParseQueryString(address.Query);

            parsedCredentials = SharedAccessSignatureHelper.ParseQuery(queryParameters, false);
            return(new Uri(address.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)));
        }
        /// <summary>
        /// Returns a shared access signature for the file.
        /// </summary>
        /// <param name="policy">A <see cref="SharedAccessFilePolicy"/> object specifying the access policy for the shared access signature.</param>
        /// <param name="headers">A <see cref="SharedAccessFileHeaders"/> object specifying optional header values to set for a file accessed with this SAS.</param>
        /// <param name="groupPolicyIdentifier">A string identifying a stored access policy.</param>
        /// <returns>A shared access signature, as a URI query string.</returns>
        public string GetSharedAccessSignature(SharedAccessFilePolicy policy, SharedAccessFileHeaders headers, string groupPolicyIdentifier)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.InvariantCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            resourceName = this.GetCanonicalName();
            StorageAccountKey accountKey   = this.ServiceClient.Credentials.Key;
            string            signature    = SharedAccessSignatureHelper.GetHash(policy, headers, groupPolicyIdentifier, resourceName, Constants.HeaderConstants.TargetStorageVersion, accountKey.KeyValue);

            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSignature(policy, headers, groupPolicyIdentifier, "f", signature, accountKey.KeyName, Constants.HeaderConstants.TargetStorageVersion);

            return(builder.ToString());
        }
        /// <summary>
        /// Returns a shared access signature for the container.
        /// </summary>
        /// <param name="policy">The access policy for the shared access signature.</param>
        /// <param name="groupPolicyIdentifier">A container-level access policy.</param>
        /// <returns>A shared access signature.</returns>
        public string GetSharedAccessSignature(SharedAccessBlobPolicy policy, string groupPolicyIdentifier)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string resourceName   = this.GetSharedAccessCanonicalName();
            string signature      = SharedAccessSignatureHelper.GetSharedAccessSignatureHashImpl(policy, groupPolicyIdentifier, resourceName, this.ServiceClient.Credentials);
            string accountKeyName = this.ServiceClient.Credentials.KeyName;

            // Future resource type changes from "c" => "container"
            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSharedAccessSignatureImpl(policy, groupPolicyIdentifier, "c", signature, accountKeyName);

            return(builder.ToString());
        }
Esempio n. 13
0
 /// <summary>
 /// Writes a collection of shared access policies to the specified stream in XML format.
 /// </summary>
 /// <param name="sharedAccessPolicies">A collection of shared access policies.</param>
 /// <param name="outputStream">An output stream.</param>
 public static void WriteSharedAccessIdentifiers(SharedAccessBlobPolicies sharedAccessPolicies, Stream outputStream)
 {
     Request.WriteSharedAccessIdentifiers(
         sharedAccessPolicies,
         outputStream,
         (policy, writer) =>
     {
         writer.WriteElementString(
             Constants.Start,
             SharedAccessSignatureHelper.GetDateTimeOrEmpty(policy.SharedAccessStartTime));
         writer.WriteElementString(
             Constants.Expiry,
             SharedAccessSignatureHelper.GetDateTimeOrEmpty(policy.SharedAccessExpiryTime));
         writer.WriteElementString(
             Constants.Permission,
             SharedAccessBlobPolicy.PermissionsToString(policy.Permissions));
     });
 }
        /// <summary>
        /// Returns a shared access signature for the blob.
        /// </summary>
        /// <param name="policy">A <see cref="SharedAccessBlobPolicy"/> object specifying the access policy for the shared access signature.</param>
        /// <param name="headers">A <see cref="SharedAccessBlobHeaders"/> object specifying optional header values to set for a blob accessed with this SAS.</param>
        /// <param name="groupPolicyIdentifier">A string identifying a stored access policy.</param>
        /// <param name="sasVersion">A string indicating the desired SAS version to use, in storage service version format. Value must be <c>2012-02-12</c> or later.</param>
        /// <returns>A shared access signature, as a URI query string.</returns>
        public string GetSharedAccessSignature(SharedAccessBlobPolicy policy, SharedAccessBlobHeaders headers, string groupPolicyIdentifier, string sasVersion)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.InvariantCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            resourceName        = this.GetCanonicalName(true);
            StorageAccountKey accountKey          = this.ServiceClient.Credentials.Key;
            string            validatedSASVersion = SharedAccessSignatureHelper.ValidateSASVersionString(sasVersion);
            string            signature           = SharedAccessSignatureHelper.GetHash(policy, headers, groupPolicyIdentifier, resourceName, validatedSASVersion, accountKey.KeyValue);

            // Future resource type changes from "c" => "container"
            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSignature(policy, headers, groupPolicyIdentifier, "b", signature, accountKey.KeyName, validatedSASVersion);

            return(builder.ToString());
        }
        /// <summary>
        /// Parse Uri for SAS (Shared access signature) information.
        /// </summary>
        /// <param name="address">The complete Uri.</param>
        /// <param name="parsedCredentials">The credentials to use.</param>
        /// <param name="parsedShareSnapshot">The parsed share snapshot.</param>
        /// <returns>The file URI without credentials or snapshot info</returns>
        /// <exception cref="System.ArgumentException">address</exception>
        /// <remarks>
        /// Validate that no other query parameters are passed in.
        /// Any SAS information will be recorded as corresponding credentials instance.
        /// If credentials is passed in and it does not match the SAS information found, an
        /// exception will be thrown.
        /// Otherwise a new client is created based on SAS information or as anonymous credentials.
        /// </remarks>
        private static Uri ParseFileQueryAndVerify(Uri address, out StorageCredentials parsedCredentials, out DateTimeOffset?parsedShareSnapshot)
        {
            parsedCredentials   = null;
            parsedShareSnapshot = null;
            if (address == null)
            {
                return(null);
            }

            if (!address.IsAbsoluteUri)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.RelativeAddressNotPermitted, address.ToString());
                throw new ArgumentException(errorMessage, "address");
            }

            IDictionary <string, string> queryParameters = HttpWebUtility.ParseQueryString(address.Query);

            parsedCredentials = SharedAccessSignatureHelper.ParseQuery(queryParameters);

            return(new Uri(address.GetComponents(UriComponents.SchemeAndServer | UriComponents.Path, UriFormat.UriEscaped)));
        }
Esempio n. 16
0
        /// <summary>
        /// Returns a shared access signature for the table.
        /// </summary>
        /// <param name="policy">The access policy for the shared access signature.</param>
        /// <param name="accessPolicyIdentifier">An access policy identifier.</param>
        /// <param name="startPartitionKey">The start partition key, or null.</param>
        /// <param name="startRowKey">The start row key, or null.</param>
        /// <param name="endPartitionKey">The end partition key, or null.</param>
        /// <param name="endRowKey">The end row key, or null.</param>
        /// <returns>A shared access signature, as a URI query string.</returns>
        /// <remarks>The query string returned includes the leading question mark.</remarks>
        /// <exception cref="InvalidOperationException">Thrown if the current credentials don't support creating a shared access signature.</exception>
        public string GetSharedAccessSignature(
            SharedAccessTablePolicy policy,
            string accessPolicyIdentifier,
            string startPartitionKey,
            string startRowKey,
            string endPartitionKey,
            string endRowKey)
        {
            if (!this.ServiceClient.Credentials.IsSharedKey)
            {
                string errorMessage = string.Format(CultureInfo.CurrentCulture, SR.CannotCreateSASWithoutAccountKey);
                throw new InvalidOperationException(errorMessage);
            }

            string            resourceName = this.GetCanonicalName();
            StorageAccountKey accountKey   = this.ServiceClient.Credentials.Key;

            string signature = SharedAccessSignatureHelper.GetSharedAccessSignatureHashImpl(
                policy,
                accessPolicyIdentifier,
                startPartitionKey,
                startRowKey,
                endPartitionKey,
                endRowKey,
                resourceName,
                accountKey.KeyValue);

            UriQueryBuilder builder = SharedAccessSignatureHelper.GetSharedAccessSignatureImpl(
                policy,
                this.Name,
                accessPolicyIdentifier,
                startPartitionKey,
                startRowKey,
                endPartitionKey,
                endRowKey,
                signature,
                accountKey.KeyName);

            return(builder.ToString());
        }