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)); }