Example #1
0
        public void AccountSAS_InvalidParameter()
        {
            SharedAccessAccountServices      service      = SharedAccessAccountServices.Blob | SharedAccessAccountServices.File | SharedAccessAccountServices.Queue | SharedAccessAccountServices.Table;
            SharedAccessAccountResourceTypes resourceType = SharedAccessAccountResourceTypes.Container | SharedAccessAccountResourceTypes.Object | SharedAccessAccountResourceTypes.Service;
            string permission = AccountSASUtils.fullPermission;
            SharedAccessProtocol sasProtocal = SharedAccessProtocol.HttpsOrHttp;
            string   iPAddressOrRange        = "0.0.0.0-255.255.255.255";
            DateTime startTime  = DateTime.Now.AddMinutes(-5);
            DateTime expiryTime = DateTime.Now.AddMinutes(60);

            //invalid permission
            Test.Assert(!CommandAgent.NewAzureStorageAccountSAS(
                            service, resourceType, "racwx", sasProtocal, iPAddressOrRange, startTime, expiryTime), "Set stored access policy with invalid permission should fail");
            if (lang == Language.PowerShell)
            {
                ExpectedContainErrorMessage("Invalid access permission");
            }
            else
            {
                ExpectedContainErrorMessage("Given  \"x\" is invalid");
            }

            //repeated permission - success
            GenerateAndValidateAccountSAS(
                service, resourceType, "rracw", sasProtocal, iPAddressOrRange, startTime, expiryTime);

            //invalid IP/IP range
            Test.Assert(!CommandAgent.NewAzureStorageAccountSAS(
                            service, resourceType, permission, null, "123.3.4a", null, null), "Set stored access policy with invalid iPAddressOrRange should fail");
            if (lang == Language.PowerShell)
            {
                ExpectedContainErrorMessage("Error when parsing IP address: IP address is invalid.");
            }
            else
            {
                ExpectedContainErrorMessage("Invalid ip range format");
            }
            Test.Assert(!CommandAgent.NewAzureStorageAccountSAS(
                            service, resourceType, permission, sasProtocal, "123.4.5.6_125.6.7.8", null, null), "Set stored access policy with invalid iPAddressOrRange should fail");
            if (lang == Language.PowerShell)
            {
                ExpectedContainErrorMessage("Error when parsing IP address: IP address is invalid.");
            }
            else
            {
                ExpectedContainErrorMessage("Invalid ip range format");
            }

            //success: start IP > end IP
            GenerateAndValidateAccountSAS(
                service, resourceType, permission, sasProtocal, "22.22.22.22-11.111.11.11", startTime, expiryTime);

            //Start time > expire Time
            Test.Assert(!CommandAgent.NewAzureStorageAccountSAS(
                            service, resourceType, permission, sasProtocal, iPAddressOrRange, DateTime.Now.AddMinutes(5), DateTime.Now.AddMinutes(-5)), "Set stored access policy with invalid Start Time should fail");
            ExpectedContainErrorMessage("The expiry time of the specified access policy should be greater than start time");
        }
        /// <summary>
        /// Get the complete query builder for creating the Shared Access Signature query.
        /// </summary>
        /// <param name="policy">The shared access policy to hash.</param>
        /// <param name="headers">The optional header values to set for a blob returned with this SAS.</param>
        /// <param name="accessPolicyIdentifier">An optional identifier for the policy.</param>
        /// <param name="resourceType">Either "b" for blobs or "c" for containers.</param>
        /// <param name="signature">The signature to use.</param>
        /// <param name="accountKeyName">The name of the key used to create the signature, or <c>null</c> if the key is implicit.</param>
        /// <param name="sasVersion">A string indicating the desired SAS version to use, in storage service version format.</param>
        /// <param name="protocols">The HTTP/HTTPS protocols for Account SAS.</param>
        /// <param name="ipAddressOrRange">The IP range for IPSAS.</param>
        /// <returns>The finished query builder.</returns>
        internal static UriQueryBuilder GetSignature(
            SharedAccessBlobPolicy policy,
            SharedAccessBlobHeaders headers,
            string accessPolicyIdentifier,
            string resourceType,
            string signature,
            string accountKeyName,
            string sasVersion,
            SharedAccessProtocol? protocols,
            IPAddressOrRange ipAddressOrRange
            )
        {
            CommonUtility.AssertNotNullOrEmpty("resourceType", resourceType);

            UriQueryBuilder builder = new UriQueryBuilder();

            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedVersion, sasVersion);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedResource, resourceType);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedIdentifier, accessPolicyIdentifier);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedKey, accountKeyName);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.Signature, signature);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedProtocols, GetProtocolString(protocols));
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedIP, ipAddressOrRange == null ? null : ipAddressOrRange.ToString());

            if (policy != null)
            {
                AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedStart, GetDateTimeOrNull(policy.SharedAccessStartTime));
                AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedExpiry, GetDateTimeOrNull(policy.SharedAccessExpiryTime));

                string permissions = SharedAccessBlobPolicy.PermissionsToString(policy.Permissions);
                if (!string.IsNullOrEmpty(permissions))
                {
                    AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedPermissions, permissions);
                }
            }

            if (headers != null)
            {
                AddEscapedIfNotNull(builder, Constants.QueryConstants.CacheControl, headers.CacheControl);
                AddEscapedIfNotNull(builder, Constants.QueryConstants.ContentType, headers.ContentType);
                AddEscapedIfNotNull(builder, Constants.QueryConstants.ContentEncoding, headers.ContentEncoding);
                AddEscapedIfNotNull(builder, Constants.QueryConstants.ContentLanguage, headers.ContentLanguage);
                AddEscapedIfNotNull(builder, Constants.QueryConstants.ContentDisposition, headers.ContentDisposition);
            }

            return builder;
        }
        /// <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();
        }
 public string GetSharedAccessSignature(SharedAccessBlobPolicy policy, SharedAccessBlobHeaders headers, string groupPolicyIdentifier, SharedAccessProtocol? protocols, IPAddressOrRange ipAddressOrRange)
 {
     throw new NotImplementedException();
 }
 /// <summary>
 /// Get blob shared access signature
 /// </summary>
 /// <param name="blob">CloudBlob object</param>
 /// <param name="accessPolicy">SharedAccessBlobPolicy object</param>
 /// <param name="policyIdentifier">The existing policy identifier.</param>
 /// <returns></returns>
 private string GetBlobSharedAccessSignature(CloudBlob blob, SharedAccessBlobPolicy accessPolicy, string policyIdentifier, SharedAccessProtocol? protocol, IPAddressOrRange iPAddressOrRange)
 {
     CloudBlobContainer container = blob.Container;
     return blob.GetSharedAccessSignature(accessPolicy, null, policyIdentifier, protocol, iPAddressOrRange);
 }
        /// <summary>
        /// Get the signature hash embedded inside the Shared Access Signature.
        /// </summary>
        /// <param name="policy">The shared access policy to hash.</param>
        /// <param name="headers">The optional header values to set for a file returned with this SAS.</param>
        /// <param name="accessPolicyIdentifier">An optional identifier for the policy.</param>
        /// <param name="resourceName">The canonical resource string, unescaped.</param>
        /// <param name="sasVersion">A string indicating the desired SAS version to use, in storage service version format.</param>
        /// <param name="protocols">The HTTP/HTTPS protocols for Account SAS.</param>
        /// <param name="ipAddressOrRange">The IP range for IPSAS.</param>
        /// <param name="keyValue">The key value retrieved as an atomic operation used for signing.</param>
        /// <returns>The signed hash.</returns>
        internal static string GetHash(
            SharedAccessFilePolicy policy,
            SharedAccessFileHeaders headers,
            string accessPolicyIdentifier,
            string resourceName,
            string sasVersion,
            SharedAccessProtocol? protocols,
            IPAddressOrRange ipAddressOrRange,
            byte[] keyValue)
        {
            CommonUtility.AssertNotNullOrEmpty("resourceName", resourceName);
            CommonUtility.AssertNotNull("keyValue", keyValue);
            CommonUtility.AssertNotNullOrEmpty("sasVersion", sasVersion);

            string permissions = null;
            DateTimeOffset? startTime = null;
            DateTimeOffset? expiryTime = null;
            if (policy != null)
            {
                permissions = SharedAccessFilePolicy.PermissionsToString(policy.Permissions);
                startTime = policy.SharedAccessStartTime;
                expiryTime = policy.SharedAccessExpiryTime;
            }

            //// StringToSign =      signedpermissions + "\n" +
            ////                     signedstart + "\n" +
            ////                     signedexpiry + "\n" +
            ////                     canonicalizedresource + "\n" +
            ////                     signedidentifier + "\n" +
            ////                     signedIP + "\n" + 
            ////                     signedProtocol + "\n" + 
            ////                     signedversion + "\n" +
            ////                     cachecontrol + "\n" +
            ////                     contentdisposition + "\n" +
            ////                     contentencoding + "\n" +
            ////                     contentlanguage + "\n" +
            ////                     contenttype 
            ////
            //// HMAC-SHA256(UTF8.Encode(StringToSign))
            ////

            string cacheControl = null;
            string contentDisposition = null;
            string contentEncoding = null;
            string contentLanguage = null;
            string contentType = null;
            if (headers != null)
            {
                cacheControl = headers.CacheControl;
                contentDisposition = headers.ContentDisposition;
                contentEncoding = headers.ContentEncoding;
                contentLanguage = headers.ContentLanguage;
                contentType = headers.ContentType;
            }

            string stringToSign = string.Format(
                                    CultureInfo.InvariantCulture,
                                    "{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}\n{12}",
                                    permissions,
                                    GetDateTimeOrEmpty(startTime),
                                    GetDateTimeOrEmpty(expiryTime),
                                    resourceName,
                                    accessPolicyIdentifier,
                                    ipAddressOrRange == null ? string.Empty : ipAddressOrRange.ToString(),
                                    GetProtocolString(protocols),
                                    sasVersion,
                                    cacheControl,
                                    contentDisposition,
                                    contentEncoding,
                                    contentLanguage,
                                    contentType);

            Logger.LogVerbose(null /* operationContext */, SR.TraceStringToSign, stringToSign);

            return CryptoUtility.ComputeHmac256(keyValue, stringToSign);
        }
        /// <summary>
        /// Get the signature hash embedded inside the Shared Access Signature.
        /// </summary>
        /// <param name="policy">The shared access policy to hash.</param>
        /// <param name="accessPolicyIdentifier">An optional identifier for the policy.</param>
        /// <param name="startPartitionKey">The start partition key, or <c>null</c>.</param>
        /// <param name="startRowKey">The start row key, or <c>null</c>.</param>
        /// <param name="endPartitionKey">The end partition key, or <c>null</c>.</param>
        /// <param name="endRowKey">The end row key, or <c>null</c>.</param>
        /// <param name="resourceName">The canonical resource string, unescaped.</param>
        /// <param name="sasVersion">A string indicating the desired SAS version to use, in storage service version format.</param>
        /// <param name="protocols">The HTTP/HTTPS protocols for Account SAS.</param>
        /// <param name="ipAddressOrRange">The IP range for IPSAS.</param>
        /// <param name="keyValue">The key value retrieved as an atomic operation used for signing.</param>
        /// <returns>The signed hash.</returns>
        internal static string GetHash(
            SharedAccessTablePolicy policy,
            string accessPolicyIdentifier,
            string startPartitionKey,
            string startRowKey,
            string endPartitionKey,
            string endRowKey,
            string resourceName,
            string sasVersion,
            SharedAccessProtocol? protocols,
            IPAddressOrRange ipAddressOrRange,
            byte[] keyValue)
        {
            CommonUtility.AssertNotNullOrEmpty("resourceName", resourceName);
            CommonUtility.AssertNotNull("keyValue", keyValue);
            CommonUtility.AssertNotNullOrEmpty("sasVersion", sasVersion);

            string permissions = null;
            DateTimeOffset? startTime = null;
            DateTimeOffset? expiryTime = null;
            if (policy != null)
            {
                permissions = SharedAccessTablePolicy.PermissionsToString(policy.Permissions);
                startTime = policy.SharedAccessStartTime;
                expiryTime = policy.SharedAccessExpiryTime;
            }

            //// StringToSign =      signedpermissions + "\n" +
            ////                     signedstart + "\n" +
            ////                     signedexpiry + "\n" +
            ////                     canonicalizedresource + "\n" +
            ////                     signedidentifier + "\n" +
            ////                     signedIP + "\n" + 
            ////                     signedProtocol + "\n" + 
            ////                     signedversion + "\n" +
            ////                     startpk + "\n" +
            ////                     startrk + "\n" +
            ////                     endpk + "\n" +
            ////                     endrk
            ////
            //// HMAC-SHA256(UTF8.Encode(StringToSign))
            //// 

            string stringToSign = string.Format(
                                     CultureInfo.InvariantCulture,
                                     "{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}",
                                     permissions,
                                     GetDateTimeOrEmpty(startTime),
                                     GetDateTimeOrEmpty(expiryTime),
                                     resourceName,
                                     accessPolicyIdentifier,
                                     ipAddressOrRange == null ? string.Empty : ipAddressOrRange.ToString(),
                                     GetProtocolString(protocols),
                                     sasVersion,
                                     startPartitionKey,
                                     startRowKey,
                                     endPartitionKey,
                                     endRowKey);

            Logger.LogVerbose(null /* operationContext */, SR.TraceStringToSign, stringToSign);
            
            return CryptoUtility.ComputeHmac256(keyValue, stringToSign);
        }
        /// <summary>
        /// Converts the specified value to either a string representation or <c>null</c>.
        /// </summary>
        /// <param name="protocols">The protocols to convert</param>
        /// <returns>A string representing the specified value.</returns>
        internal static string GetProtocolString(SharedAccessProtocol? protocols)
        {
            if (!protocols.HasValue)
            {
                return null;
            }

            if ((protocols.Value != SharedAccessProtocol.HttpsOnly) && (protocols.Value != SharedAccessProtocol.HttpsOrHttp))
            {
                throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, SR.InvalidProtocolsInSAS, protocols.Value));
            }

            return protocols.Value == SharedAccessProtocol.HttpsOnly ? "https" : "https,http";
        }
        /// <summary>
        /// Get the complete query builder for creating the Shared Access Signature query.
        /// </summary>
        /// <param name="policy">The shared access policy to hash.</param>
        /// <param name="tableName">The name of the table associated with this shared access signature.</param>
        /// <param name="accessPolicyIdentifier">An optional identifier for the policy.</param>
        /// <param name="startPartitionKey">The start partition key, or <c>null</c>.</param>
        /// <param name="startRowKey">The start row key, or <c>null</c>.</param>
        /// <param name="endPartitionKey">The end partition key, or <c>null</c>.</param>
        /// <param name="endRowKey">The end row key, or <c>null</c>.</param>
        /// <param name="signature">The signature to use.</param>
        /// <param name="accountKeyName">The name of the key used to create the signature, or <c>null</c> if the key is implicit.</param>
        /// <param name="sasVersion">A string indicating the desired SAS version to use, in storage service version format.</param>
        /// <param name="protocols">The HTTP/HTTPS protocols for Account SAS.</param>
        /// <param name="ipAddressOrRange">The IP range for IPSAS.</param>
        /// <returns>The finished query builder.</returns>
        internal static UriQueryBuilder GetSignature(
            SharedAccessTablePolicy policy,
            string tableName,
            string accessPolicyIdentifier,
            string startPartitionKey,
            string startRowKey,
            string endPartitionKey,
            string endRowKey,
            string signature,
            string accountKeyName,
            string sasVersion,
            SharedAccessProtocol? protocols,
            IPAddressOrRange ipAddressOrRange)
        {          
            CommonUtility.AssertNotNull("signature", signature);

            UriQueryBuilder builder = new UriQueryBuilder();
 
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedVersion, sasVersion);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SasTableName, tableName);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.StartPartitionKey, startPartitionKey);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.StartRowKey, startRowKey);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.EndPartitionKey, endPartitionKey);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.EndRowKey, endRowKey);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedIdentifier, accessPolicyIdentifier);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedKey, accountKeyName);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.Signature, signature);
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedProtocols, GetProtocolString(protocols));
            AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedIP, ipAddressOrRange == null ? null : ipAddressOrRange.ToString());

            if (policy != null)
            {
                AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedStart, GetDateTimeOrNull(policy.SharedAccessStartTime));
                AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedExpiry, GetDateTimeOrNull(policy.SharedAccessExpiryTime));

                string permissions = SharedAccessTablePolicy.PermissionsToString(policy.Permissions);
                if (!string.IsNullOrEmpty(permissions))
                {
                    AddEscapedIfNotNull(builder, Constants.QueryConstants.SignedPermissions, permissions);
                }
            }

            return builder;
        }
        /// <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;
            string signature = SharedAccessSignatureHelper.GetHash(policy, headers, groupPolicyIdentifier, resourceName, Constants.HeaderConstants.TargetStorageVersion, protocols, ipAddressOrRange, accountKey.KeyValue);

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

            return builder.ToString();
        }
        /// <summary>
        /// Converts the specified value to either a string representation or <c>null</c>.
        /// </summary>
        /// <param name="protocols">The protocols to convert</param>
        /// <returns>A string representing the specified value.</returns>
        internal static string GetProtocolString(SharedAccessProtocol? protocols)
        {
            if (!protocols.HasValue)
            {
                return null;
            }

            return protocols.Value == SharedAccessProtocol.HttpsOnly ? "https" : "https,http";
        }
        /// <summary>
        /// Get blob shared access signature
        /// </summary>
        /// <param name="blob">CloudBlob object</param>
        /// <param name="accessPolicy">SharedAccessBlobPolicy object</param>
        /// <param name="policyIdentifier">The existing policy identifier.</param>
        /// <returns></returns>
        private string GetBlobSharedAccessSignature(CloudBlob blob, SharedAccessBlobPolicy accessPolicy, string policyIdentifier, SharedAccessProtocol protocol, IPAddressOrRange iPAddressOrRange)
        {
            CloudBlobContainer container = blob.Container;

            return(blob.GetSharedAccessSignature(accessPolicy, null, policyIdentifier, protocol, iPAddressOrRange));
        }