private string GetContainerSASWithLighthouse(BlobServiceClient service, string storageAccount,
                                                     string storageContainer, string blobName, StorageSharedKeyCredential credential)
        {
            BlobSasBuilder blobSasBuilder;

            BlobContainerClient       container            = service.GetBlobContainerClient(storageContainer);
            BlobContainerAccessPolicy policy               = container.GetAccessPolicy();
            BlobSignedIdentifier      blobSignedIdentifier = policy.SignedIdentifiers.FirstOrDefault(x => x.Id == "expiresapr");

            // if stored access policy exists, use it, otherwise, specify permissions
            if (blobSignedIdentifier != null)
            {
                blobSasBuilder = new BlobSasBuilder
                {
                    BlobContainerName = storageContainer,
                    Identifier        = blobSignedIdentifier.Id
                };

                /* load test how fast we can generate SAS token
                 * for (int ii = 0; ii < 100000; ++ii )
                 * {
                 *  var blobSas = new BlobSasBuilder
                 *  {
                 *      BlobContainerName = storageContainer,
                 *      BlobName = "abc" + ii,
                 *      Identifier = blobSignedIdentifier.Id
                 *  };
                 *  var param = blobSas.ToSasQueryParameters(credential).ToString();
                 * }*/
            }
            else
            {
                DateTimeOffset expiresOn = DateTimeOffset.UtcNow.AddHours(2);
                blobSasBuilder = new BlobSasBuilder
                {
                    BlobContainerName = storageContainer,
                    ExpiresOn         = expiresOn,
                };
                blobSasBuilder.SetPermissions(
                    BlobContainerSasPermissions.Read |
                    BlobContainerSasPermissions.Create |
                    BlobContainerSasPermissions.List);
            }

            var    sasQueryParameters = blobSasBuilder.ToSasQueryParameters(credential).ToString();
            String uri = String.IsNullOrEmpty(blobName) ?
                         String.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list&{2}",
                                       storageAccount,
                                       storageContainer,
                                       sasQueryParameters.ToString()) :
                         String.Format("https://{0}.blob.core.windows.net/{1}/{2}?{3}",
                                       storageAccount,
                                       storageContainer,
                                       blobName,
                                       sasQueryParameters.ToString());

            return(uri);
        }
        internal string SetAzureContainerStoredAccessPolicy(IStorageBlobManagement localChannel, string containerName, string policyName, DateTime?startTime, DateTime?expiryTime, string permission, bool noStartTime, bool noExpiryTime)
        {
            //Get container instance, Get existing permissions
            CloudBlobContainer                 container_Track1  = Channel.GetContainerReference(containerName);
            BlobContainerClient                container         = AzureStorageContainer.GetTrack2BlobContainerClient(container_Track1, Channel.StorageContext, ClientOptions);
            BlobContainerAccessPolicy          accessPolicy      = container.GetAccessPolicy(cancellationToken: CmdletCancellationToken).Value;
            IEnumerable <BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers;

            //Set the policy with new value
            BlobSignedIdentifier signedIdentifier = null;

            foreach (BlobSignedIdentifier identifier in signedIdentifiers)
            {
                if (identifier.Id == policyName)
                {
                    signedIdentifier = identifier;
                }
            }

            if (signedIdentifier == null)
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.PolicyNotFound, policyName));
            }
            if (noStartTime)
            {
                signedIdentifier.AccessPolicy.PolicyStartsOn = DateTimeOffset.MinValue;
            }

            else if (startTime != null)
            {
                signedIdentifier.AccessPolicy.PolicyStartsOn = StartTime.Value.ToUniversalTime();
            }
            if (noExpiryTime)
            {
                signedIdentifier.AccessPolicy.PolicyExpiresOn = DateTimeOffset.MinValue;
            }
            else if (ExpiryTime != null)
            {
                signedIdentifier.AccessPolicy.PolicyExpiresOn = ExpiryTime.Value.ToUniversalTime();
            }

            if (this.Permission != null)
            {
                signedIdentifier.AccessPolicy.Permissions = this.Permission;
                signedIdentifier.AccessPolicy.Permissions = AccessPolicyHelper.OrderBlobPermission(this.Permission);
            }

            //Set permissions back to container
            container.SetAccessPolicy(accessPolicy.BlobPublicAccess, signedIdentifiers, BlobRequestConditions, CmdletCancellationToken);
            WriteObject(AccessPolicyHelper.ConstructPolicyOutputPSObject <BlobSignedIdentifier>(signedIdentifier));
            return(policyName);
        }
예제 #3
0
        /// <summary>
        /// set the access level of specified container
        /// </summary>
        /// <param name="name">container name</param>
        /// <param name="accessLevel">access level in ("off", "blob", "container")</param>
        internal async Task SetContainerAcl(long taskId, IStorageBlobManagement localChannel, string name, BlobContainerPublicAccessType accessLevel)
        {
            if (!NameUtil.IsValidContainerName(name))
            {
                throw new ArgumentException(String.Format(Resources.InvalidContainerName, name));
            }

            BlobRequestOptions requestOptions = RequestOptions;

            CloudBlobContainer  container       = localChannel.GetContainerReference(name);
            BlobContainerClient containerClient = AzureStorageContainer.GetTrack2BlobContainerClient(container, this.Channel.StorageContext, ClientOptions);

            // Get container permission and set the public access as input
            BlobContainerAccessPolicy accessPolicy;

            try
            {
                accessPolicy = containerClient.GetAccessPolicy(null, this.CmdletCancellationToken);
            }
            catch (global::Azure.RequestFailedException e) when(e.Status == 404)
            {
                throw new ResourceNotFoundException(String.Format(Resources.ContainerNotFound, name));
            }
            PublicAccessType publicAccessType = PublicAccessType.None;

            switch (accessLevel)
            {
            case BlobContainerPublicAccessType.Blob:
                publicAccessType = PublicAccessType.Blob;
                break;

            case BlobContainerPublicAccessType.Container:
                publicAccessType = PublicAccessType.BlobContainer;
                break;

            case BlobContainerPublicAccessType.Off:
                publicAccessType = PublicAccessType.None;
                break;

            default:
            case BlobContainerPublicAccessType.Unknown:
                throw new ArgumentOutOfRangeException("Permission");
            }
            await containerClient.SetAccessPolicyAsync(publicAccessType, accessPolicy.SignedIdentifiers, null, this.CmdletCancellationToken).ConfigureAwait(false);

            if (PassThru)
            {
                AzureStorageContainer storageContainer = new AzureStorageContainer(containerClient, Channel.StorageContext);
                storageContainer.SetTrack2Permission();
                OutputStream.WriteObject(taskId, storageContainer);
            }
        }
예제 #4
0
        /// <summary>
        /// Get a BlobSignedIdentifier from contaienr with a specific Id
        /// </summary>
        public static BlobSignedIdentifier GetBlobSignedIdentifier(BlobContainerClient container, string identifierId, CancellationToken cancellationToken)
        {
            IEnumerable <BlobSignedIdentifier> signedIdentifiers = container.GetAccessPolicy(cancellationToken: cancellationToken).Value.SignedIdentifiers;

            foreach (BlobSignedIdentifier identifier in signedIdentifiers)
            {
                if (identifier.Id == identifierId)
                {
                    return(identifier);
                }
            }
            throw new ArgumentException(string.Format(Resources.InvalidAccessPolicy, identifierId));
        }
예제 #5
0
        public void RemoveAccessPolicyIfExists(string containerName, string policyName)
        {
            var container = new BlobContainerClient(connectionString, containerName);

            var exisitingPolicies = container.GetAccessPolicy().Value.SignedIdentifiers.ToList();
            var policyToBeRemoved = exisitingPolicies.SingleOrDefault(x => x.Id == policyName);

            if (policyToBeRemoved == null)
            {
                return;
            }

            exisitingPolicies.Remove(policyToBeRemoved);
            container.SetAccessPolicy(permissions: exisitingPolicies);
        }
        internal string CreateAzureContainerStoredAccessPolicy(IStorageBlobManagement localChannel, string containerName, string policyName, DateTime?startTime, DateTime?expiryTime, string permission)
        {
            if (!NameUtil.IsValidStoredAccessPolicyName(policyName))
            {
                throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Resources.InvalidAccessPolicyName, policyName));
            }

            //Get container instance, Get existing permissions
            CloudBlobContainer                 container_Track1  = Channel.GetContainerReference(containerName);
            BlobContainerClient                container         = AzureStorageContainer.GetTrack2BlobContainerClient(container_Track1, Channel.StorageContext, ClientOptions);
            BlobContainerAccessPolicy          accessPolicy      = container.GetAccessPolicy(cancellationToken: CmdletCancellationToken).Value;
            IEnumerable <BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers;

            //Add new policy
            foreach (BlobSignedIdentifier identifier in signedIdentifiers)
            {
                if (identifier.Id == policyName)
                {
                    throw new ResourceAlreadyExistException(String.Format(CultureInfo.CurrentCulture, Resources.PolicyAlreadyExists, policyName));
                }
            }
            BlobSignedIdentifier signedIdentifier = new BlobSignedIdentifier();

            signedIdentifier.Id           = policyName;
            signedIdentifier.AccessPolicy = new BlobAccessPolicy();
            if (StartTime != null)
            {
                signedIdentifier.AccessPolicy.PolicyStartsOn = StartTime.Value.ToUniversalTime();
            }
            if (ExpiryTime != null)
            {
                signedIdentifier.AccessPolicy.PolicyExpiresOn = ExpiryTime.Value.ToUniversalTime();
            }
            signedIdentifier.AccessPolicy.Permissions = AccessPolicyHelper.OrderBlobPermission(this.Permission);
            var newsignedIdentifiers = new List <BlobSignedIdentifier>(signedIdentifiers);

            newsignedIdentifiers.Add(signedIdentifier);

            //Set permissions back to container
            container.SetAccessPolicy(accessPolicy.BlobPublicAccess, newsignedIdentifiers, BlobRequestConditions, CmdletCancellationToken);
            return(policyName);
        }
예제 #7
0
        internal bool RemoveAzureContainerStoredAccessPolicy(IStorageBlobManagement localChannel, string containerName, string policyName)
        {
            bool   success = false;
            string result  = string.Empty;

            //Get container instance, Get existing permissions
            CloudBlobContainer                 container_Track1  = Channel.GetContainerReference(containerName);
            BlobContainerClient                container         = AzureStorageContainer.GetTrack2BlobContainerClient(container_Track1, Channel.StorageContext, ClientOptions);
            BlobContainerAccessPolicy          accessPolicy      = container.GetAccessPolicy(cancellationToken: CmdletCancellationToken).Value;
            IEnumerable <BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers;

            //remove policy
            BlobSignedIdentifier signedIdentifier = null;

            foreach (BlobSignedIdentifier identifier in signedIdentifiers)
            {
                if (identifier.Id == policyName)
                {
                    signedIdentifier = identifier;
                }
            }

            if (signedIdentifier == null)
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.PolicyNotFound, policyName));
            }

            if (ShouldProcess(policyName, "Remove policy"))
            {
                List <BlobSignedIdentifier> policyList = new List <BlobSignedIdentifier>(signedIdentifiers);
                policyList.Remove(signedIdentifier);

                //Set permissions back to container
                container.SetAccessPolicy(accessPolicy.BlobPublicAccess, policyList, BlobRequestConditions, CmdletCancellationToken);
                success = true;
            }

            return(success);
        }
        public async Task CreateSharedAccessPolicy()
        {
            string connectionString             = this.ConnectionString;
            string containerName                = Randomize("sample-container");
            BlobContainerClient containerClient = new BlobContainerClient(connectionString, containerName);

            try
            {
                await containerClient.CreateIfNotExistsAsync();

                #region Snippet:SampleSnippetsBlobMigration_SharedAccessPolicy
                // Create one or more stored access policies.
                List <BlobSignedIdentifier> signedIdentifiers = new List <BlobSignedIdentifier>
                {
                    new BlobSignedIdentifier
                    {
                        Id           = "mysignedidentifier",
                        AccessPolicy = new BlobAccessPolicy
                        {
                            StartsOn    = DateTimeOffset.UtcNow.AddHours(-1),
                            ExpiresOn   = DateTimeOffset.UtcNow.AddDays(1),
                            Permissions = "rw"
                        }
                    }
                };
                // Set the container's access policy.
                await containerClient.SetAccessPolicyAsync(permissions : signedIdentifiers);

                #endregion

                BlobContainerAccessPolicy containerAccessPolicy = containerClient.GetAccessPolicy();
                Assert.AreEqual(signedIdentifiers.First().Id, containerAccessPolicy.SignedIdentifiers.First().Id);
            }
            finally
            {
                await containerClient.DeleteIfExistsAsync();
            }
        }
        public void SetTrack2Permission(BlobContainerAccessPolicy accesspolicy = null)
        {
            // Try to get container permission if not input it, and container not deleted
            if (accesspolicy == null && (this.IsDeleted == null || !this.IsDeleted.Value))
            {
                try
                {
                    accesspolicy = privateBlobContainerClient.GetAccessPolicy().Value;
                }
                catch (global::Azure.RequestFailedException e) when(e.Status == 403 || e.Status == 404)
                {
                    // 404 Not found, or 403 Forbidden means we don't have permission to query the Permission of the specified container.
                    // Just skip return container permission in this case.
                }
            }

            if (accesspolicy != null)
            {
                AccessPolicy = accesspolicy;

                switch (accesspolicy.BlobPublicAccess)
                {
                case PublicAccessType.Blob:
                    PublicAccess = BlobContainerPublicAccessType.Blob;
                    break;

                case PublicAccessType.BlobContainer:
                    PublicAccess = BlobContainerPublicAccessType.Container;
                    break;

                case PublicAccessType.None:
                default:
                    PublicAccess = BlobContainerPublicAccessType.Off;
                    break;
                }
            }
        }
예제 #10
0
        //-------------------------------------------------
        // Set container public access level
        //-------------------------------------------------

        // <Snippet_SetPublicContainerPermissions>
        public static void SetPublicContainerPermissions(BlobContainerClient container)
        {
            container.SetAccessPolicy(PublicAccessType.BlobContainer);
            Console.WriteLine("Container {0} - permissions set to {1}",
                              container.Name, container.GetAccessPolicy().Value);
        }
        /// <summary>
        /// set the access level of specified container
        /// </summary>
        /// <param name="name">container name</param>
        /// <param name="accessLevel">access level in ("off", "blob", "container")</param>
        internal async Task SetContainerAcl(long taskId, IStorageBlobManagement localChannel, string name, BlobContainerPublicAccessType accessLevel)
        {
            if (!NameUtil.IsValidContainerName(name))
            {
                throw new ArgumentException(String.Format(Resources.InvalidContainerName, name));
            }

            BlobRequestOptions requestOptions  = RequestOptions;
            AccessCondition    accessCondition = null;
            bool needUseTrack2 = false;

            CloudBlobContainer container = localChannel.GetContainerReference(name);

            // Get container permission and set the public access as input
            BlobContainerPermissions permissions = null;

            try
            {
                permissions = localChannel.GetContainerPermissions(container, null, requestOptions, OperationContext);
            }
            catch (StorageException e) when(e.IsNotFoundException())
            {
                throw new ResourceNotFoundException(String.Format(Resources.ContainerNotFound, name));
            }
            catch (StorageException e) when(e.IsConflictException())
            {
                // 409 Conflict, might caused by the container has an Stored access policy contains a permission that is not supported by Track1 SDK API veresion, so switch to Track2 SDK
                needUseTrack2 = true;
            }

            if (!needUseTrack2) // Track1
            {
                permissions.PublicAccess = accessLevel;

                await localChannel.SetContainerPermissionsAsync(container, permissions, accessCondition, requestOptions, OperationContext, CmdletCancellationToken).ConfigureAwait(false);

                if (PassThru)
                {
                    WriteCloudContainerObject(taskId, localChannel, container, permissions);
                }
            }
            else // Track2
            {
                BlobContainerClient containerClient = AzureStorageContainer.GetTrack2BlobContainerClient(container, this.Channel.StorageContext, ClientOptions);

                // Get container permission and set the public access as input
                BlobContainerAccessPolicy accessPolicy;

                accessPolicy = containerClient.GetAccessPolicy(null, this.CmdletCancellationToken);

                PublicAccessType publicAccessType = PublicAccessType.None;
                switch (accessLevel)
                {
                case BlobContainerPublicAccessType.Blob:
                    publicAccessType = PublicAccessType.Blob;
                    break;

                case BlobContainerPublicAccessType.Container:
                    publicAccessType = PublicAccessType.BlobContainer;
                    break;

                case BlobContainerPublicAccessType.Off:
                    publicAccessType = PublicAccessType.None;
                    break;

                default:
                case BlobContainerPublicAccessType.Unknown:
                    throw new ArgumentOutOfRangeException("Permission");
                }
                await containerClient.SetAccessPolicyAsync(publicAccessType, accessPolicy.SignedIdentifiers, null, this.CmdletCancellationToken).ConfigureAwait(false);

                if (PassThru)
                {
                    AzureStorageContainer storageContainer = new AzureStorageContainer(container, null);
                    storageContainer.Context = localChannel.StorageContext;
                    storageContainer.SetTrack2Permission();
                    OutputStream.WriteObject(taskId, storageContainer);
                }
            }
        }
예제 #12
0
        public override void ExecuteCmdlet()
        {
            CloudBlob blob = null;

            if (ParameterSetName == BlobNamePipelineParmeterSetWithPermission ||
                ParameterSetName == BlobNamePipelineParmeterSetWithPolicy)
            {
                blob = GetCloudBlobByName(Container, Blob);
            }
            else
            {
                blob = this.CloudBlob;
            }

            // When the input context is Oauth bases, can't generate normal SAS, but UserDelegationSas
            bool generateUserDelegationSas = false;

            if (Channel != null && Channel.StorageContext != null && Channel.StorageContext.StorageAccount.Credentials.IsToken)
            {
                if (ShouldProcess(blob.Name, "Generate User Delegation SAS, since input Storage Context is OAuth based."))
                {
                    generateUserDelegationSas = true;
                    if (!string.IsNullOrEmpty(accessPolicyIdentifier))
                    {
                        throw new ArgumentException("When input Storage Context is OAuth based, Saved Policy is not supported.", "Policy");
                    }
                }
                else
                {
                    return;
                }
            }

            if (!(blob is InvalidCloudBlob) && !UseTrack2SDK())
            {
                SharedAccessBlobPolicy accessPolicy = new SharedAccessBlobPolicy();
                bool shouldSetExpiryTime            = SasTokenHelper.ValidateContainerAccessPolicy(Channel, blob.Container.Name, accessPolicy, accessPolicyIdentifier);
                SetupAccessPolicy(accessPolicy, shouldSetExpiryTime);
                string sasToken = GetBlobSharedAccessSignature(blob, accessPolicy, accessPolicyIdentifier, Protocol, Util.SetupIPAddressOrRangeForSAS(IPAddressOrRange), generateUserDelegationSas);

                if (FullUri)
                {
                    string fullUri = blob.SnapshotQualifiedUri.ToString();
                    if (blob.IsSnapshot)
                    {
                        // Since snapshot URL already has '?', need remove '?' in the first char of sas
                        fullUri = fullUri + "&" + sasToken.Substring(1);
                    }
                    else
                    {
                        fullUri = fullUri + sasToken;
                    }
                    WriteObject(fullUri);
                }
                else
                {
                    WriteObject(sasToken);
                }
            }
            else // Use Track2 SDk
            {
                BlobBaseClient blobClient;
                if (this.BlobBaseClient != null)
                {
                    blobClient = this.BlobBaseClient;
                }
                else
                {
                    blobClient = AzureStorageBlob.GetTrack2BlobClient(blob, Channel.StorageContext, this.ClientOptions);
                }

                BlobSasBuilder sasBuilder;
                if (ParameterSetName == BlobNamePipelineParmeterSetWithPolicy || ParameterSetName == BlobPipelineParameterSetWithPolicy)
                {
                    BlobContainerClient container = AzureStorageContainer.GetTrack2BlobContainerClient(Channel.GetContainerReference(blobClient.BlobContainerName), Channel.StorageContext, ClientOptions);
                    IEnumerable <BlobSignedIdentifier> signedIdentifiers = container.GetAccessPolicy(cancellationToken: CmdletCancellationToken).Value.SignedIdentifiers;
                    BlobSignedIdentifier signedIdentifier = null;
                    foreach (BlobSignedIdentifier identifier in signedIdentifiers)
                    {
                        if (identifier.Id == this.Policy)
                        {
                            signedIdentifier = identifier;
                            break;
                        }
                    }
                    if (signedIdentifier is null)
                    {
                        throw new ArgumentException(string.Format(Resources.InvalidAccessPolicy, this.Policy));
                    }
                    sasBuilder = new BlobSasBuilder
                    {
                        BlobContainerName = blobClient.BlobContainerName,
                        BlobName          = blobClient.Name,
                        Identifier        = this.Policy
                    };

                    if (this.StartTime != null)
                    {
                        if (signedIdentifier.AccessPolicy.StartsOn != DateTimeOffset.MinValue)
                        {
                            throw new InvalidOperationException(Resources.SignedStartTimeMustBeOmitted);
                        }
                        else
                        {
                            sasBuilder.StartsOn = this.StartTime.Value.ToUniversalTime();
                        }
                    }

                    if (this.ExpiryTime != null)
                    {
                        if (signedIdentifier.AccessPolicy.ExpiresOn != DateTimeOffset.MinValue)
                        {
                            throw new ArgumentException(Resources.SignedExpiryTimeMustBeOmitted);
                        }
                        else
                        {
                            sasBuilder.ExpiresOn = this.ExpiryTime.Value.ToUniversalTime();
                        }
                    }
                    else if (signedIdentifier.AccessPolicy.ExpiresOn == DateTimeOffset.MinValue)
                    {
                        if (sasBuilder.StartsOn != DateTimeOffset.MinValue)
                        {
                            sasBuilder.ExpiresOn = sasBuilder.StartsOn.ToUniversalTime().AddHours(1);
                        }
                        else
                        {
                            sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
                        }
                    }

                    if (this.Permission != null)
                    {
                        if (signedIdentifier.AccessPolicy.Permissions != null)
                        {
                            throw new ArgumentException(Resources.SignedPermissionsMustBeOmitted);
                        }
                        else
                        {
                            sasBuilder.SetPermissions(this.Permission);
                        }
                    }
                }
                else
                {
                    sasBuilder = new BlobSasBuilder
                    {
                        BlobContainerName = blobClient.BlobContainerName,
                        BlobName          = blobClient.Name,
                    };
                    sasBuilder.SetPermissions(this.Permission);
                    if (this.StartTime != null)
                    {
                        sasBuilder.StartsOn = this.StartTime.Value.ToUniversalTime();
                    }
                    if (this.ExpiryTime != null)
                    {
                        sasBuilder.ExpiresOn = this.ExpiryTime.Value.ToUniversalTime();
                    }
                    else
                    {
                        if (sasBuilder.StartsOn != DateTimeOffset.MinValue)
                        {
                            sasBuilder.ExpiresOn = sasBuilder.StartsOn.AddHours(1).ToUniversalTime();
                        }
                        else
                        {
                            sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
                        }
                    }
                }
                if (this.IPAddressOrRange != null)
                {
                    sasBuilder.IPRange = Util.SetupIPAddressOrRangeForSASTrack2(this.IPAddressOrRange);
                }
                if (this.Protocol != null)
                {
                    if (this.Protocol.Value == SharedAccessProtocol.HttpsOrHttp)
                    {
                        sasBuilder.Protocol = SasProtocol.HttpsAndHttp;
                    }
                    else //HttpsOnly
                    {
                        sasBuilder.Protocol = SasProtocol.Https;
                    }
                }
                if (Util.GetVersionIdFromBlobUri(blobClient.Uri) != null)
                {
                    sasBuilder.BlobVersionId = Util.GetVersionIdFromBlobUri(blobClient.Uri);
                }
                if (Util.GetSnapshotTimeFromBlobUri(blobClient.Uri) != null)
                {
                    sasBuilder.Snapshot = Util.GetSnapshotTimeFromBlobUri(blobClient.Uri).Value.ToString("o");
                }

                string sasToken = GetBlobSharedAccessSignature(blobClient, sasBuilder, generateUserDelegationSas);
                if (sasToken[0] != '?')
                {
                    sasToken = "?" + sasToken;
                }

                if (FullUri)
                {
                    string fullUri = blobClient.Uri.ToString();
                    if (blob.IsSnapshot)
                    {
                        // Since snapshot URL already has '?', need remove '?' in the first char of sas
                        fullUri = fullUri + "&" + sasToken.Substring(1);
                    }
                    else
                    {
                        fullUri = fullUri + sasToken;
                    }
                    WriteObject(fullUri);
                }
                else
                {
                    WriteObject(sasToken);
                }
            }
        }