Skip to content

Commit 42f86ed

Browse files
yifanz7blueww
andauthored
[Storage] Migrate New-AzStorageQueueSASToken to Track2 SDK (#21966)
* migrate queue sas token * Fix per comments * fix client options --------- Co-authored-by: Wei Wei <[email protected]>
1 parent 8b23da4 commit 42f86ed

File tree

5 files changed

+208
-32
lines changed

5 files changed

+208
-32
lines changed

src/Storage/Storage.Management/ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
- `Copy-AzStorageBlob`
2525
- `Set-AzStorageBlobContent`
2626
- `Start-AzStorageBlobCopy`
27+
* Migrated the following Azure Queue dataplane cmdlets from 'Microsoft.Azure.Storage.Queue' to 'Azure.Storage.Queue'
28+
- `New-AzStorageQueueSASToken`
2729
* Add warning messages for an upcoming breaking change when creating SAS token
2830
- `New-AzStorageBlobSasToken`
2931
- `New-AzStorageContainerSasToken`

src/Storage/Storage/Common/SasTokenHelper.cs

Lines changed: 147 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Common
3232
using global::Azure.Storage.Files.DataLake;
3333
using global::Azure.Storage.Files.Shares;
3434
using global::Azure.Storage.Files.Shares.Models;
35+
using global::Azure.Storage.Queues.Models;
36+
using global::Azure.Storage.Queues;
3537

3638
internal class SasTokenHelper
3739
{
@@ -266,7 +268,7 @@ public static BlobSignedIdentifier GetBlobSignedIdentifier(BlobContainerClient c
266268
}
267269

268270
/// <summary>
269-
/// Get a ShareSignedIdentifier from contaienr with a specific Id
271+
/// Get a ShareSignedIdentifier from share with a specific Id
270272
/// </summary>
271273
public static ShareSignedIdentifier GetShareSignedIdentifier(ShareClient share, string identifierId, CancellationToken cancellationToken)
272274
{
@@ -281,10 +283,25 @@ public static ShareSignedIdentifier GetShareSignedIdentifier(ShareClient share,
281283
throw new ArgumentException(string.Format(Resources.InvalidAccessPolicy, identifierId));
282284
}
283285

286+
/// <summary>
287+
/// Get a QueueSignedIdentifier from queue with a specific id
288+
/// </summary>
289+
public static QueueSignedIdentifier GetQueueSignedIdentifier(QueueClient queue, string identifierId, CancellationToken cancellationToken)
290+
{
291+
IEnumerable<QueueSignedIdentifier> signedIdentifiers = queue.GetAccessPolicy(cancellationToken: cancellationToken).Value;
292+
foreach (QueueSignedIdentifier identifier in signedIdentifiers)
293+
{
294+
if (identifier.Id == identifierId)
295+
{
296+
return identifier;
297+
}
298+
}
299+
throw new ArgumentException(string.Format(Resources.InvalidAccessPolicy, identifierId));
300+
}
284301

285302

286303
/// <summary>
287-
/// Create a blob SAS build from Blob Object
304+
/// Create a share SAS build from file Object
288305
/// </summary>
289306
public static ShareSasBuilder SetShareSasBuilder_FromFile(ShareFileClient file,
290307
ShareSignedIdentifier signedIdentifier = null,
@@ -306,7 +323,7 @@ public static ShareSasBuilder SetShareSasBuilder_FromFile(ShareFileClient file,
306323
}
307324

308325
/// <summary>
309-
/// Create a blob SAS build from container Object
326+
/// Create a share SAS build from share Object
310327
/// </summary>
311328
public static ShareSasBuilder SetShareSasBuilder_FromShare(ShareClient share,
312329
ShareSignedIdentifier signedIdentifier = null,
@@ -328,7 +345,115 @@ public static ShareSasBuilder SetShareSasBuilder_FromShare(ShareClient share,
328345
}
329346

330347
/// <summary>
331-
/// Create a blob SAS build from Blob Object
348+
/// Create a Queue SAS builder
349+
/// </summary>
350+
public static QueueSasBuilder SetQueueSasbuilder(QueueClient queue,
351+
QueueSignedIdentifier signedIdentifier = null,
352+
string permission = null,
353+
DateTime? startTime = null,
354+
DateTime? expiryTime = null,
355+
string iPAddressOrRange = null,
356+
SharedAccessProtocol? protocol = null)
357+
{
358+
QueueSasBuilder sasBuilder = new QueueSasBuilder
359+
{
360+
QueueName = queue.Name,
361+
};
362+
363+
if (signedIdentifier != null)
364+
{
365+
sasBuilder.Identifier = signedIdentifier.Id;
366+
367+
if (startTime != null)
368+
{
369+
if (signedIdentifier.AccessPolicy.StartsOn != DateTimeOffset.MinValue && signedIdentifier.AccessPolicy.StartsOn != null)
370+
{
371+
throw new InvalidOperationException(Resources.SignedStartTimeMustBeOmitted);
372+
}
373+
else
374+
{
375+
sasBuilder.StartsOn = startTime.Value.ToUniversalTime();
376+
}
377+
}
378+
if (expiryTime != null)
379+
{
380+
if (signedIdentifier.AccessPolicy.ExpiresOn != DateTimeOffset.MinValue && signedIdentifier.AccessPolicy.ExpiresOn != null)
381+
{
382+
throw new ArgumentException(Resources.SignedExpiryTimeMustBeOmitted);
383+
}
384+
else
385+
{
386+
sasBuilder.ExpiresOn = expiryTime.Value.ToUniversalTime();
387+
}
388+
}
389+
// Set up expiry time if it is not set by user input or the policy
390+
else if (signedIdentifier.AccessPolicy.ExpiresOn == DateTimeOffset.MinValue || signedIdentifier.AccessPolicy.ExpiresOn == null)
391+
{
392+
if (sasBuilder.StartsOn != DateTimeOffset.MinValue && sasBuilder.StartsOn != null)
393+
{
394+
sasBuilder.ExpiresOn = sasBuilder.StartsOn.ToUniversalTime().AddHours(1);
395+
}
396+
else
397+
{
398+
sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
399+
}
400+
}
401+
if (permission != null)
402+
{
403+
if (signedIdentifier.AccessPolicy.Permissions != null)
404+
{
405+
throw new ArgumentException(Resources.SignedPermissionsMustBeOmitted);
406+
}
407+
else
408+
{
409+
sasBuilder.SetPermissions(permission, true);
410+
}
411+
}
412+
}
413+
else
414+
{
415+
sasBuilder.SetPermissions(permission, true);
416+
417+
if (startTime != null)
418+
{
419+
sasBuilder.StartsOn = startTime.Value.ToUniversalTime();
420+
}
421+
if (expiryTime != null)
422+
{
423+
sasBuilder.ExpiresOn = expiryTime.Value.ToUniversalTime();
424+
}
425+
else
426+
{
427+
if (sasBuilder.StartsOn != DateTimeOffset.MinValue)
428+
{
429+
sasBuilder.ExpiresOn = sasBuilder.StartsOn.AddHours(1).ToUniversalTime();
430+
}
431+
else
432+
{
433+
sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
434+
}
435+
}
436+
}
437+
if (iPAddressOrRange != null)
438+
{
439+
sasBuilder.IPRange = Util.SetupIPAddressOrRangeForSASTrack2(iPAddressOrRange);
440+
}
441+
if (protocol != null)
442+
{
443+
if (protocol.Value == SharedAccessProtocol.HttpsOrHttp)
444+
{
445+
sasBuilder.Protocol = SasProtocol.HttpsAndHttp;
446+
}
447+
else //HttpsOnly
448+
{
449+
sasBuilder.Protocol = SasProtocol.Https;
450+
}
451+
}
452+
return sasBuilder;
453+
}
454+
455+
/// <summary>
456+
/// Create a share SAS builder
332457
/// </summary>
333458
public static ShareSasBuilder SetShareSasBuilder(string shareName,
334459
string filePath = null,
@@ -373,7 +498,7 @@ public static ShareSasBuilder SetShareSasBuilder(string shareName,
373498
sasBuilder.ExpiresOn = ExpiryTime.Value.ToUniversalTime();
374499
}
375500
}
376-
else if (signedIdentifier.AccessPolicy.PolicyExpiresOn == DateTimeOffset.MinValue && signedIdentifier.AccessPolicy.PolicyExpiresOn != null)
501+
else if (signedIdentifier.AccessPolicy.PolicyExpiresOn == DateTimeOffset.MinValue || signedIdentifier.AccessPolicy.PolicyExpiresOn == null)
377502
{
378503
if (sasBuilder.StartsOn != DateTimeOffset.MinValue && sasBuilder.StartsOn != null)
379504
{
@@ -458,6 +583,21 @@ public static string GetFileSharedAccessSignature(AzureStorageContext context, S
458583
}
459584
}
460585

586+
/// <summary>
587+
/// Get Queue SAS string
588+
/// </summary>
589+
public static string GetQueueSharedAccessSignature(AzureStorageContext context, QueueSasBuilder sasBuilder, CancellationToken cancellationToken)
590+
{
591+
if (context != null && context.StorageAccount != null && context.StorageAccount.Credentials != null && context.StorageAccount.Credentials.IsSharedKey)
592+
{
593+
return sasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(context.StorageAccountName, context.StorageAccount.Credentials.ExportBase64EncodedKey())).ToString();
594+
}
595+
else
596+
{
597+
throw new InvalidOperationException("Create Queue service SAS only supported with SharedKey credentail.");
598+
}
599+
}
600+
461601

462602
/// <summary>
463603
/// Create a blob SAS build from Blob Object
@@ -561,7 +701,7 @@ public static BlobSasBuilder SetBlobSasBuilder(string containerName,
561701
sasBuilder.ExpiresOn = ExpiryTime.Value.ToUniversalTime();
562702
}
563703
}
564-
else if (signedIdentifier.AccessPolicy.PolicyExpiresOn == DateTimeOffset.MinValue && signedIdentifier.AccessPolicy.PolicyExpiresOn != null)
704+
else if (signedIdentifier.AccessPolicy.PolicyExpiresOn == DateTimeOffset.MinValue || signedIdentifier.AccessPolicy.PolicyExpiresOn == null)
565705
{
566706
if (sasBuilder.StartsOn != DateTimeOffset.MinValue && sasBuilder.StartsOn != null)
567707
{
@@ -741,7 +881,7 @@ public static string GetDatalakeGen2SharedAccessSignature(AzureStorageContext co
741881
}
742882

743883
/// <summary>
744-
/// Create a blob SAS build from Blob Object
884+
/// Create a account SAS builder
745885
/// </summary>
746886
public static AccountSasBuilder SetAccountSasBuilder(SharedAccessAccountServices Service,
747887
SharedAccessAccountResourceTypes type,

src/Storage/Storage/Common/Util.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Common
3333
using global::Azure.Storage.Files.Shares.Models;
3434
using global::Azure.Storage.Files.DataLake;
3535
using global::Azure.Storage.Files.Shares;
36+
using global::Azure.Storage.Queues;
3637

3738
internal static class Util
3839
{
@@ -797,6 +798,25 @@ public static ShareClient GetTrack2ShareReference(string shareName, AzureStorage
797798
}
798799
}
799800

801+
public static QueueClient GetTrack2QueueClient(string queueName, AzureStorageContext context, QueueClientOptions options)
802+
{
803+
if (context == null || string.IsNullOrEmpty(context.ConnectionString))
804+
{
805+
throw new ArgumentException(Resources.DefaultStorageCredentialsNotFound);
806+
}
807+
808+
string connectionString = context.ConnectionString;
809+
if (context != null && context.StorageAccount != null && context.StorageAccount.Credentials != null && context.StorageAccount.Credentials.IsSAS)
810+
{
811+
connectionString = connectionString.Replace("SharedAccessSignature=?", "SharedAccessSignature=");
812+
}
813+
814+
QueueClient queueClient;
815+
816+
queueClient = new QueueClient(connectionString, queueName, options);
817+
return queueClient;
818+
}
819+
800820
/// <summary>
801821
/// Get SnapshotQualifiedUri without credential from a blob/file service item Uri.
802822
/// </summary>

src/Storage/Storage/Queue/Cmdlet/NewAzureStorageQueueSasToken.cs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@
1414

1515
namespace Microsoft.WindowsAzure.Commands.Storage.Queue.Cmdlet
1616
{
17+
using global::Azure.Storage.Queues;
18+
using global::Azure.Storage.Queues.Models;
19+
using global::Azure.Storage.Sas;
20+
using Microsoft.Azure.Storage;
1721
using Microsoft.WindowsAzure.Commands.Storage.Common;
1822
using Microsoft.WindowsAzure.Commands.Storage.Model.Contract;
19-
using Microsoft.Azure.Storage;
20-
using Microsoft.Azure.Storage.Queue;
2123
using System;
2224
using System.Management.Automation;
2325
using System.Security.Permissions;
@@ -39,7 +41,7 @@ public class NewAzureStorageQueueSasTokenCommand : StorageQueueBaseCmdlet
3941

4042
[Alias("N", "Queue")]
4143
[Parameter(Position = 0, Mandatory = true,
42-
HelpMessage = "Table Name",
44+
HelpMessage = "Queue Name",
4345
ValueFromPipeline = true,
4446
ValueFromPipelineByPropertyName = true)]
4547
[ValidateNotNullOrEmpty]
@@ -56,7 +58,7 @@ public string Policy
5658

5759
[Parameter(
5860
Mandatory = false,
59-
HelpMessage = "Permissions for a container. Permissions can be any not-empty subset of \"raup\".",
61+
HelpMessage = "Permissions for a queue. Permissions can be any not-empty subset of \"raup\".",
6062
ParameterSetName = SasPermissionParameterSet)]
6163
[ValidateNotNullOrEmpty]
6264
public string Permission { get; set; }
@@ -109,36 +111,31 @@ public NewAzureStorageQueueSasTokenCommand(IStorageQueueManagement channel)
109111
public override void ExecuteCmdlet()
110112
{
111113
if (String.IsNullOrEmpty(Name)) return;
112-
CloudQueue queue = Channel.GetQueueReference(Name);
113-
SharedAccessQueuePolicy policy = new SharedAccessQueuePolicy();
114-
bool shouldSetExpiryTime = SasTokenHelper.ValidateQueueAccessPolicy(Channel, queue.Name, policy, accessPolicyIdentifier);
115-
SetupAccessPolicy(policy, shouldSetExpiryTime);
116-
string sasToken = queue.GetSharedAccessSignature(policy, accessPolicyIdentifier, Protocol, Util.SetupIPAddressOrRangeForSAS(IPAddressOrRange));
114+
115+
QueueClient queueClient = Util.GetTrack2QueueClient(this.Name, (AzureStorageContext)this.Context, this.ClientOptions);
116+
QueueSignedIdentifier identifier = null;
117+
if (!string.IsNullOrEmpty(this.Policy))
118+
{
119+
identifier = SasTokenHelper.GetQueueSignedIdentifier(queueClient, this.Policy, CmdletCancellationToken);
120+
}
121+
122+
QueueSasBuilder sasBuilder = SasTokenHelper.SetQueueSasbuilder(queueClient, identifier, this.Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol);
123+
string sasToken = SasTokenHelper.GetQueueSharedAccessSignature((AzureStorageContext)this.Context, sasBuilder, CmdletCancellationToken);
124+
125+
if (sasToken[0] != '?')
126+
{
127+
sasToken = "?" + sasToken;
128+
}
117129

118130
if (FullUri)
119131
{
120-
string fullUri = queue.Uri.ToString() + sasToken;
132+
string fullUri = SasTokenHelper.GetFullUriWithSASToken(queueClient.Uri.AbsoluteUri.ToString(), sasToken);
121133
WriteObject(fullUri);
122134
}
123135
else
124136
{
125137
WriteObject(sasToken);
126138
}
127139
}
128-
129-
/// <summary>
130-
/// Update the access policy
131-
/// </summary>
132-
/// <param name="policy">Access policy object</param>
133-
/// <param name="shouldSetExpiryTime">Should set the default expiry time</param>
134-
private void SetupAccessPolicy(SharedAccessQueuePolicy policy, bool shouldSetExpiryTime)
135-
{
136-
DateTimeOffset? accessStartTime;
137-
DateTimeOffset? accessEndTime;
138-
SasTokenHelper.SetupAccessPolicyLifeTime(StartTime, ExpiryTime, out accessStartTime, out accessEndTime, shouldSetExpiryTime);
139-
policy.SharedAccessStartTime = accessStartTime;
140-
policy.SharedAccessExpiryTime = accessEndTime;
141-
AccessPolicyHelper.SetupAccessPolicyPermission(policy, Permission);
142-
}
143140
}
144141
}

src/Storage/Storage/Queue/StorageQueueBaseCmdlet.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Common
1616
{
1717
using Microsoft.WindowsAzure.Commands.Storage.Model.Contract;
1818
using Microsoft.Azure.Storage.Queue;
19+
using global::Azure.Storage.Queues;
20+
using global::Azure.Core;
21+
using Microsoft.WindowsAzure.Commands.Common;
1922

2023
/// <summary>
2124
/// base class for azure queue cmdlet
@@ -52,5 +55,19 @@ public QueueRequestOptions RequestOptions
5255
return (QueueRequestOptions)GetRequestOptions(StorageServiceType.Queue);
5356
}
5457
}
58+
59+
public QueueClientOptions ClientOptions
60+
{
61+
get
62+
{
63+
if (clientOptions == null)
64+
{
65+
clientOptions = new QueueClientOptions();
66+
clientOptions.AddPolicy(new UserAgentPolicy(ApiConstants.UserAgentHeaderValue), HttpPipelinePosition.PerCall);
67+
}
68+
return clientOptions;
69+
}
70+
}
71+
private QueueClientOptions clientOptions = null;
5572
}
5673
}

0 commit comments

Comments
 (0)