< Summary

Class:Azure.Storage.Sas.ShareSasBuilder
Assembly:Azure.Storage.Files.Shares
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Files.Shares\src\Sas\ShareSasBuilder.cs
Covered lines:90
Uncovered lines:7
Coverable lines:97
Total lines:336
Line coverage:92.7% (90 of 97)
Covered branches:17
Total branches:20
Branch coverage:85% (17 of 20)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_Version()-100%100%
get_Protocol()-100%100%
get_StartsOn()-100%100%
get_ExpiresOn()-100%100%
get_Permissions()-100%100%
get_IPRange()-100%100%
get_Identifier()-100%100%
get_ShareName()-100%100%
get_FilePath()-100%100%
get_Resource()-100%100%
get_CacheControl()-100%100%
get_ContentDisposition()-100%100%
get_ContentEncoding()-100%100%
get_ContentLanguage()-100%100%
get_ContentType()-100%100%
SetPermissions(...)-100%100%
SetPermissions(...)-0%100%
SetPermissions(...)-100%100%
SetPermissions(...)-100%100%
SetPermissions(...)-100%100%
.cctor()-100%100%
ToSasQueryParameters(...)-100%83.33%
GetCanonicalName(...)-100%100%
ToString()-0%100%
Equals(...)-0%100%
GetHashCode()-0%100%
EnsureState()-81.82%80%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Files.Shares\src\Sas\ShareSasBuilder.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.ComponentModel;
 7using System.Text;
 8using Azure.Storage.Files.Shares;
 9
 10namespace Azure.Storage.Sas
 11{
 12    /// <summary>
 13    /// <see cref="ShareSasBuilder"/> is used to generate a Shared Access
 14    /// Signature (SAS) for an Azure Storage share, directory, or file.
 15    ///
 16    /// For more information, see
 17    /// <see href="https://docs.microsoft.com/en-us/rest/api/storageservices/constructing-a-service-sas">
 18    /// Creating a Service SAS</see>.
 19    /// </summary>
 20    public class ShareSasBuilder
 21    {
 22        /// <summary>
 23        /// The storage service version to use to authenticate requests made
 24        /// with this shared access signature, and the service version to use
 25        /// when handling requests made with this shared access signature.
 26        /// </summary>
 15227        public string Version { get; set; }
 28
 29        /// <summary>
 30        /// The optional signed protocol field specifies the protocol
 31        /// permitted for a request made with the SAS.  Possible values are
 32        /// <see cref="SasProtocol.HttpsAndHttp"/>, <see cref="SasProtocol.Https"/>,
 33        /// and <see cref="SasProtocol.None"/>.
 34        /// </summary>
 10235        public SasProtocol Protocol { get; set; }
 36
 37        /// <summary>
 38        /// Optionally specify the time at which the shared access signature
 39        /// becomes valid.  If omitted when DateTimeOffset.MinValue is used,
 40        /// start time for this call is assumed to be the time when the
 41        /// storage service receives the request.
 42        /// </summary>
 10643        public DateTimeOffset StartsOn { get; set; }
 44
 45        /// <summary>
 46        /// The time at which the shared access signature becomes invalid.
 47        /// This field must be omitted if it has been specified in an
 48        /// associated stored access policy.
 49        /// </summary>
 13650        public DateTimeOffset ExpiresOn { get; set; }
 51
 52        /// <summary>
 53        /// The permissions associated with the shared access signature. The
 54        /// user is restricted to operations allowed by the permissions. This
 55        /// field must be omitted if it has been specified in an associated
 56        /// stored access policy.  The <see cref="ShareFileSasPermissions"/>,
 57        /// <see cref="ShareSasPermissions"/>, or <see cref="ShareAccountSasPermissions"/>
 58        /// can be used to create the permissions string.
 59        /// </summary>
 13460        public string Permissions { get; private set; }
 61
 62        /// <summary>
 63        /// Specifies an IP address or a range of IP addresses from which to
 64        /// accept requests. If the IP address from which the request
 65        /// originates does not match the IP address or address range
 66        /// specified on the SAS token, the request is not authenticated.
 67        /// When specifying a range of IP addresses, note that the range is
 68        /// inclusive.
 69        /// </summary>
 10070        public SasIPRange IPRange { get; set; }
 71
 72        /// <summary>
 73        /// An optional unique value up to 64 characters in length that
 74        /// correlates to an access policy specified for the share.
 75        /// </summary>
 11876        public string Identifier { get; set; }
 77
 78        /// <summary>
 79        /// The name of the share being made accessible.
 80        /// </summary>
 7681        public string ShareName { get; set; }
 82
 83        /// <summary>
 84        /// The path of the file or directory being made accessible, or <see cref="string.Empty"/>
 85        /// for a share SAS.
 86        /// </summary>
 10287        public string FilePath { get; set; }
 88
 89        /// <summary>
 90        /// Specifies which resources are accessible via the shared access
 91        /// signature.
 92        ///
 93        /// Specify "f" if the shared resource is a file. This grants access
 94        /// to the content and metadata of the file.
 95        ///
 96        /// Specify "s" if the shared resource is a share. This grants access
 97        /// to the content and metadata of any file in the share, and to the
 98        /// list of directories and files in the share.
 99        /// </summary>
 76100        public string Resource { get; set; }
 101
 102        /// <summary>
 103        /// Override the value returned for Cache-Control response header.
 104        /// </summary>
 78105        public string CacheControl { get; set; }
 106
 107        /// <summary>
 108        /// Override the value returned for Content-Disposition response
 109        /// header.
 110        /// </summary>
 78111        public string ContentDisposition { get; set; }
 112
 113        /// <summary>
 114        /// Override the value returned for Cache-Encoding response header.
 115        /// </summary>
 78116        public string ContentEncoding { get; set; }
 117
 118        /// <summary>
 119        /// Override the value returned for Cache-Language response header.
 120        /// </summary>
 78121        public string ContentLanguage { get; set; }
 122
 123        /// <summary>
 124        /// Override the value returned for Cache-Type response header.
 125        /// </summary>
 78126        public string ContentType { get; set; }
 127
 128        /// <summary>
 129        /// Sets the permissions for a file SAS.
 130        /// </summary>
 131        /// <param name="permissions">
 132        /// <see cref="ShareFileSasPermissions"/> containing the allowed permissions.
 133        /// </param>
 134        public void SetPermissions(ShareFileSasPermissions permissions)
 135        {
 26136            Permissions = permissions.ToPermissionsString();
 26137        }
 138
 139        /// <summary>
 140        /// Sets the permissions for a file account level SAS.
 141        /// </summary>
 142        /// <param name="permissions">
 143        /// <see cref="ShareAccountSasPermissions"/> containing the allowed permissions.
 144        /// </param>
 145        public void SetPermissions(ShareAccountSasPermissions permissions)
 146        {
 0147            Permissions = permissions.ToPermissionsString();
 0148        }
 149
 150        /// <summary>
 151        /// Sets the permissions for a share SAS.
 152        /// </summary>
 153        /// <param name="permissions">
 154        /// <see cref="ShareSasPermissions"/> containing the allowed permissions.
 155        /// </param>
 156        public void SetPermissions(ShareSasPermissions permissions)
 157        {
 4158            Permissions = permissions.ToPermissionsString();
 4159        }
 160
 161        /// <summary>
 162        /// Sets the permissions for the SAS using a raw permissions string.
 163        /// </summary>
 164        /// <param name="rawPermissions">
 165        /// Raw permissions string for the SAS.
 166        /// </param>
 167        /// <param name="normalize">
 168        /// If the permissions should be validated and correctly ordered.
 169        /// </param>
 170        public void SetPermissions(
 171            string rawPermissions,
 172            bool normalize = default)
 173        {
 6174            if (normalize)
 175            {
 6176                rawPermissions = SasExtensions.ValidateAndSanitizeRawPermissions(
 6177                    permissions: rawPermissions,
 6178                    validPermissionsInOrder: s_validPermissionsInOrder);
 179            }
 180
 4181            SetPermissions(rawPermissions);
 4182        }
 183
 184        /// <summary>
 185        /// Sets the permissions for the SAS using a raw permissions string.
 186        /// </summary>
 187        /// <param name="rawPermissions">Raw permissions string for the SAS.</param>
 188        public void SetPermissions(string rawPermissions)
 189        {
 4190            Permissions = rawPermissions;
 4191        }
 192
 1193        private static readonly List<char> s_validPermissionsInOrder = new List<char>
 1194        {
 1195            Constants.Sas.Permissions.Read,
 1196            Constants.Sas.Permissions.Add,
 1197            Constants.Sas.Permissions.Create,
 1198            Constants.Sas.Permissions.Write,
 1199            Constants.Sas.Permissions.Delete,
 1200            Constants.Sas.Permissions.DeleteBlobVersion,
 1201            Constants.Sas.Permissions.List,
 1202            Constants.Sas.Permissions.Tag,
 1203            Constants.Sas.Permissions.Update,
 1204            Constants.Sas.Permissions.Process,
 1205            Constants.Sas.Permissions.FilterByTags,
 1206        };
 207
 208        /// <summary>
 209        /// Use an account's <see cref="StorageSharedKeyCredential"/> to sign this
 210        /// shared access signature values to produce the proper SAS query
 211        /// parameters for authenticating requests.
 212        /// </summary>
 213        /// <param name="sharedKeyCredential">
 214        /// The storage account's <see cref="StorageSharedKeyCredential"/>.
 215        /// </param>
 216        /// <returns>
 217        /// The <see cref="SasQueryParameters"/> used for authenticating requests.
 218        /// </returns>
 219        public SasQueryParameters ToSasQueryParameters(StorageSharedKeyCredential sharedKeyCredential)
 220        {
 38221            sharedKeyCredential = sharedKeyCredential ?? throw Errors.ArgumentNull(nameof(sharedKeyCredential));
 222
 36223            EnsureState();
 224
 36225            var startTime = SasExtensions.FormatTimesForSasSigning(StartsOn);
 36226            var expiryTime = SasExtensions.FormatTimesForSasSigning(ExpiresOn);
 227
 228            // String to sign: http://msdn.microsoft.com/en-us/library/azure/dn140255.aspx
 36229            var stringToSign = string.Join("\n",
 36230                Permissions,
 36231                startTime,
 36232                expiryTime,
 36233                GetCanonicalName(sharedKeyCredential.AccountName, ShareName ?? string.Empty, FilePath ?? string.Empty),
 36234                Identifier,
 36235                IPRange.ToString(),
 36236                SasExtensions.ToProtocolString(Protocol),
 36237                Version,
 36238                CacheControl,
 36239                ContentDisposition,
 36240                ContentEncoding,
 36241                ContentLanguage,
 36242                ContentType);
 243
 36244            var signature = StorageSharedKeyCredentialInternals.ComputeSasSignature(sharedKeyCredential, stringToSign);
 245
 36246            var p = SasQueryParametersInternals.Create(
 36247                version: Version,
 36248                services: default,
 36249                resourceTypes: default,
 36250                protocol: Protocol,
 36251                startsOn: StartsOn,
 36252                expiresOn: ExpiresOn,
 36253                ipRange: IPRange,
 36254                identifier: Identifier,
 36255                resource: Resource,
 36256                permissions: Permissions,
 36257                signature: signature,
 36258                cacheControl: CacheControl,
 36259                contentDisposition: ContentDisposition,
 36260                contentEncoding: ContentEncoding,
 36261                contentLanguage: ContentLanguage,
 36262                contentType: ContentType);
 36263            return p;
 264        }
 265
 266        /// <summary>
 267        /// Computes the canonical name for a share or file resource for SAS signing.
 268        /// Share: "/file/account/sharename"
 269        /// File:  "/file/account/sharename/filename"
 270        /// File:  "/file/account/sharename/directoryname/filename"
 271        /// </summary>
 272        /// <param name="account">The name of the storage account.</param>
 273        /// <param name="shareName">The name of the share.</param>
 274        /// <param name="filePath">The path of the file.</param>
 275        /// <returns>The canonical resource name.</returns>
 276        private static string GetCanonicalName(string account, string shareName, string filePath)
 36277            => !string.IsNullOrEmpty(filePath)
 36278               ? $"/file/{account}/{shareName}/{filePath.Replace("\\", "/")}"
 36279               : $"/file/{account}/{shareName}";
 280
 281        /// <summary>
 282        /// Returns a string that represents the current object.
 283        /// </summary>
 284        /// <returns>A string that represents the current object.</returns>
 285        [EditorBrowsable(EditorBrowsableState.Never)]
 0286        public override string ToString() => base.ToString();
 287
 288        /// <summary>
 289        /// Check if two FileSasBuilder instances are equal.
 290        /// </summary>
 291        /// <param name="obj">The instance to compare to.</param>
 292        /// <returns>True if they're equal, false otherwise.</returns>
 293        [EditorBrowsable(EditorBrowsableState.Never)]
 0294        public override bool Equals(object obj) => base.Equals(obj);
 295
 296        /// <summary>
 297        /// Get a hash code for the FileSasBuilder.
 298        /// </summary>
 299        /// <returns>Hash code for the FileSasBuilder.</returns>
 300        [EditorBrowsable(EditorBrowsableState.Never)]
 0301        public override int GetHashCode() => base.GetHashCode();
 302
 303        /// <summary>
 304        /// Ensure the <see cref="ShareSasBuilder"/>'s properties are in a
 305        /// consistent state.
 306        /// </summary>
 307        private void EnsureState()
 308        {
 36309            if (Identifier == default)
 310            {
 28311                if (ExpiresOn == default)
 312                {
 0313                    throw Errors.SasMissingData(nameof(ExpiresOn));
 314                }
 28315                if (string.IsNullOrEmpty(Permissions))
 316                {
 0317                    throw Errors.SasMissingData(nameof(Permissions));
 318                }
 319            }
 320
 36321            if (string.IsNullOrEmpty(FilePath))
 322            {
 14323                Resource = Constants.Sas.Resource.Share;
 324            }
 325            else
 326            {
 22327                Resource = Constants.Sas.Resource.File;
 328            }
 329
 36330            if (string.IsNullOrEmpty(Version))
 331            {
 32332                Version = SasQueryParameters.DefaultSasVersion;
 333            }
 36334        }
 335    }
 336}