Skip to content

Commit 570ecbd

Browse files
bluewwVeryEarly
andauthored
[Storage] Remove prefix '?' of the created SAS token (#22993)
* [Storage] Remove prefix '?' of the created SAS token * revise the code * Update src/Storage/Storage.Management/ChangeLog.md Co-authored-by: Yabo Hu <[email protected]> --------- Co-authored-by: Yabo Hu <[email protected]>
1 parent 5a1dc42 commit 570ecbd

14 files changed

+94
-240
lines changed

src/Storage/Storage.Management/ChangeLog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@
2222
* Supported creationTime filter in Blob Inventory
2323
- `New-AzStorageBlobInventoryPolicyRule`
2424
* Upgraded Azure.Core to 1.35.0.
25+
* [Breaking Change] Removed prefix '?' of the created SAS token
26+
- `New-AzStorageBlobSasToken`
27+
- `New-AzStorageContainerSasToken`
28+
- `New-AzStorageAccountSasToken`
29+
- `New-AzStorageFileSasToken`
30+
- `New-AzStorageShareSasToken`
31+
- `New-AzStorageQueueSasToken`
32+
- `New-AzStorageTableSasToken`
2533

2634
## Version 5.10.1
2735
* Added warning messages for an upcoming breaking change that the output Permissions will be changed to a string when creating and updating a Queue access policy

src/Storage/Storage/Blob/Cmdlet/NewAzureStorageBlobSasToken.cs

Lines changed: 30 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet
3030
using global::Azure.Storage;
3131
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
3232

33-
[GenericBreakingChangeWithVersion("The leading question mark '?' of the created SAS token will be removed in a future release.", "11.0.0", "6.0.0")]
3433
[Cmdlet("New", Azure.Commands.ResourceManager.Common.AzureRMConstants.AzurePrefix + "StorageBlobSASToken", DefaultParameterSetName = BlobNamePipelineParmeterSetWithPermission, SupportsShouldProcess = true), OutputType(typeof(String))]
3534
public class NewAzureStorageBlobSasTokenCommand : StorageCloudBlobCmdletBase
3635
{
@@ -182,7 +181,7 @@ public override void ExecuteCmdlet()
182181

183182
// When the input context is Oauth bases, can't generate normal SAS, but UserDelegationSas
184183
bool generateUserDelegationSas = false;
185-
if (Channel != null && Channel.StorageContext != null && Channel.StorageContext.StorageAccount.Credentials !=null && Channel.StorageContext.StorageAccount.Credentials.IsToken)
184+
if (Channel != null && Channel.StorageContext != null && Channel.StorageContext.StorageAccount.Credentials != null && Channel.StorageContext.StorageAccount.Credentials.IsToken)
186185
{
187186
if (ShouldProcess(blob.Name, "Generate User Delegation SAS, since input Storage Context is OAuth based."))
188187
{
@@ -197,83 +196,42 @@ public override void ExecuteCmdlet()
197196
return;
198197
}
199198
}
200-
201-
if (!(blob is InvalidCloudBlob) && !UseTrack2Sdk())
199+
//Get blob instance
200+
BlobBaseClient blobClient;
201+
if (this.BlobBaseClient != null)
202202
{
203-
204-
SharedAccessBlobPolicy accessPolicy = new SharedAccessBlobPolicy();
205-
bool shouldSetExpiryTime = SasTokenHelper.ValidateContainerAccessPolicy(Channel, blob.Container.Name, accessPolicy, accessPolicyIdentifier);
206-
SetupAccessPolicy(accessPolicy, shouldSetExpiryTime);
207-
string sasToken = GetBlobSharedAccessSignature(blob, accessPolicy, accessPolicyIdentifier, Protocol, Util.SetupIPAddressOrRangeForSAS(IPAddressOrRange), generateUserDelegationSas);
208-
209-
if (FullUri)
210-
{
211-
string fullUri = blob.SnapshotQualifiedUri.ToString();
212-
if (blob.IsSnapshot)
213-
{
214-
// Since snapshot URL already has '?', need remove '?' in the first char of sas
215-
fullUri = fullUri + "&" + sasToken.Substring(1);
216-
}
217-
else
218-
{
219-
fullUri = fullUri + sasToken;
220-
}
221-
WriteObject(fullUri);
222-
}
223-
else
224-
{
225-
WriteObject(sasToken);
226-
}
203+
blobClient = this.BlobBaseClient;
227204
}
228-
else // Use Track2 SDk
205+
else
229206
{
230-
//Get blob instance
231-
BlobBaseClient blobClient;
232-
if (this.BlobBaseClient != null)
233-
{
234-
blobClient = this.BlobBaseClient;
235-
}
236-
else
237-
{
238-
blobClient = AzureStorageBlob.GetTrack2BlobClient(blob, Channel.StorageContext, this.ClientOptions);
239-
}
207+
blobClient = AzureStorageBlob.GetTrack2BlobClient(blob, Channel.StorageContext, this.ClientOptions);
208+
}
240209

241-
// Get contaienr saved policy if any
242-
BlobSignedIdentifier identifier = null;
243-
if (ParameterSetName == BlobNamePipelineParmeterSetWithPolicy || ParameterSetName == BlobPipelineParameterSetWithPolicy)
244-
{
245-
BlobContainerClient container = AzureStorageContainer.GetTrack2BlobContainerClient(Channel.GetContainerReference(blobClient.BlobContainerName), Channel.StorageContext, ClientOptions);
246-
identifier = SasTokenHelper.GetBlobSignedIdentifier(container, this.Policy, CmdletCancellationToken);
247-
}
210+
// Get contaienr saved policy if any
211+
BlobSignedIdentifier identifier = null;
212+
if (ParameterSetName == BlobNamePipelineParmeterSetWithPolicy || ParameterSetName == BlobPipelineParameterSetWithPolicy)
213+
{
214+
BlobContainerClient container = AzureStorageContainer.GetTrack2BlobContainerClient(Channel.GetContainerReference(blobClient.BlobContainerName), Channel.StorageContext, ClientOptions);
215+
identifier = SasTokenHelper.GetBlobSignedIdentifier(container, this.Policy, CmdletCancellationToken);
216+
}
248217

249-
//Create SAS builder
250-
BlobSasBuilder sasBuilder = SasTokenHelper.SetBlobSasBuilder_FromBlob(blobClient, identifier, this.Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol, this.EncryptionScope);
218+
//Create SAS builder
219+
BlobSasBuilder sasBuilder = SasTokenHelper.SetBlobSasBuilder_FromBlob(blobClient, identifier, this.Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol, this.EncryptionScope);
251220

252-
//Create SAS and ourput
253-
string sasToken = SasTokenHelper.GetBlobSharedAccessSignature(Channel.StorageContext, sasBuilder, generateUserDelegationSas, ClientOptions, CmdletCancellationToken);
254-
if (sasToken[0] != '?')
255-
{
256-
sasToken = "?" + sasToken;
257-
}
221+
//Create SAS and output
222+
string sasToken = SasTokenHelper.GetBlobSharedAccessSignature(Channel.StorageContext, sasBuilder, generateUserDelegationSas, ClientOptions, CmdletCancellationToken);
223+
224+
// remove prefix "?" of SAS if any
225+
sasToken = Util.GetSASStringWithoutQuestionMark(sasToken);
258226

259-
if (FullUri)
260-
{
261-
string fullUri = blobClient.Uri.ToString();
262-
if (blob.IsSnapshot)
263-
{
264-
// Since snapshot URL already has '?', need remove '?' in the first char of sas
265-
fullUri = fullUri + "&" + sasToken.Substring(1);
266-
}
267-
else
268-
{
269-
fullUri = fullUri + sasToken;
270-
}
271-
WriteObject(fullUri);
272-
}
273-
else
274-
{
275-
WriteObject(sasToken);
276-
}
227+
if (FullUri)
228+
{
229+
string fullUri = SasTokenHelper.GetFullUriWithSASToken(blobClient.Uri.ToString(), sasToken);
230+
WriteObject(fullUri);
231+
}
232+
else
233+
{
234+
WriteObject(sasToken);
277235
}
278236
}
279237

src/Storage/Storage/Blob/Cmdlet/NewAzureStorageContainerSasToken.cs

Lines changed: 22 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet
2727
using global::Azure.Storage.Sas;
2828
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
2929

30-
[GenericBreakingChangeWithVersion("The leading question mark '?' of the created SAS token will be removed in a future release.", "11.0.0", "6.0.0")]
3130
[Cmdlet("New", Azure.Commands.ResourceManager.Common.AzureRMConstants.AzurePrefix + "StorageContainerSASToken", SupportsShouldProcess = true), OutputType(typeof(String))]
3231
public class NewAzureStorageContainerSasTokenCommand : StorageCloudBlobCmdletBase
3332
{
@@ -129,7 +128,7 @@ public override void ExecuteCmdlet()
129128

130129
// When the input context is Oauth bases, can't generate normal SAS, but UserDelegationSas
131130
bool generateUserDelegationSas = false;
132-
if (Channel!=null && Channel.StorageContext!= null && Channel.StorageContext.StorageAccount.Credentials != null && Channel.StorageContext.StorageAccount.Credentials.IsToken)
131+
if (Channel != null && Channel.StorageContext != null && Channel.StorageContext.StorageAccount.Credentials != null && Channel.StorageContext.StorageAccount.Credentials.IsToken)
133132
{
134133
if (ShouldProcess(Name, "Generate User Delegation SAS, since input Storage Context is OAuth based."))
135134
{
@@ -144,67 +143,34 @@ public override void ExecuteCmdlet()
144143
return;
145144
}
146145
}
146+
//Get container instance
147+
CloudBlobContainer container_Track1 = Channel.GetContainerReference(Name);
148+
BlobContainerClient container = AzureStorageContainer.GetTrack2BlobContainerClient(container_Track1, Channel.StorageContext, ClientOptions);
147149

148-
if (!UseTrack2Sdk()) // Track1
150+
// Get contaienr saved policy if any
151+
Track2Models.BlobSignedIdentifier identifier = null;
152+
if (ParameterSetName == SasPolicyParmeterSet)
149153
{
150-
CloudBlobContainer container = Channel.GetContainerReference(Name);
151-
SharedAccessBlobPolicy accessPolicy = new SharedAccessBlobPolicy();
152-
bool shouldSetExpiryTime = SasTokenHelper.ValidateContainerAccessPolicy(Channel, container.Name, accessPolicy, accessPolicyIdentifier);
153-
SetupAccessPolicy(accessPolicy, shouldSetExpiryTime);
154-
string sasToken;
155-
156-
if (generateUserDelegationSas)
157-
{
158-
UserDelegationKey userDelegationKey = Channel.GetUserDelegationKey(accessPolicy.SharedAccessStartTime, accessPolicy.SharedAccessExpiryTime, null, null, OperationContext);
159-
sasToken = container.GetUserDelegationSharedAccessSignature(userDelegationKey, accessPolicy, null, Protocol, Util.SetupIPAddressOrRangeForSAS(IPAddressOrRange));
160-
}
161-
else
162-
{
163-
sasToken = container.GetSharedAccessSignature(accessPolicy, accessPolicyIdentifier, Protocol, Util.SetupIPAddressOrRangeForSAS(IPAddressOrRange));
164-
}
165-
166-
if (FullUri)
167-
{
168-
string fullUri = SasTokenHelper.GetFullUriWithSASToken(container.Uri.AbsoluteUri.ToString(), sasToken);
169-
WriteObject(fullUri);
170-
}
171-
else
172-
{
173-
WriteObject(sasToken);
174-
}
154+
identifier = SasTokenHelper.GetBlobSignedIdentifier(container, this.Policy, CmdletCancellationToken);
175155
}
176-
else //Track2
177-
{
178-
//Get container instance
179-
CloudBlobContainer container_Track1 = Channel.GetContainerReference(Name);
180-
BlobContainerClient container = AzureStorageContainer.GetTrack2BlobContainerClient(container_Track1, Channel.StorageContext, ClientOptions);
181156

182-
// Get contaienr saved policy if any
183-
Track2Models.BlobSignedIdentifier identifier = null;
184-
if (ParameterSetName == SasPolicyParmeterSet)
185-
{
186-
identifier = SasTokenHelper.GetBlobSignedIdentifier(container, this.Policy, CmdletCancellationToken);
187-
}
157+
//Create SAS builder
158+
BlobSasBuilder sasBuilder = SasTokenHelper.SetBlobSasBuilder_FromContainer(container, identifier, this.Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol, this.EncryptionScope);
188159

189-
//Create SAS builder
190-
BlobSasBuilder sasBuilder = SasTokenHelper.SetBlobSasBuilder_FromContainer(container, identifier, this.Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol, this.EncryptionScope);
160+
//Create SAS and output it
161+
string sasToken = SasTokenHelper.GetBlobSharedAccessSignature(Channel.StorageContext, sasBuilder, generateUserDelegationSas, ClientOptions, CmdletCancellationToken);
191162

192-
//Create SAS and output it
193-
string sasToken = SasTokenHelper.GetBlobSharedAccessSignature(Channel.StorageContext, sasBuilder, generateUserDelegationSas, ClientOptions, CmdletCancellationToken);
194-
if (sasToken[0] != '?')
195-
{
196-
sasToken = "?" + sasToken;
197-
}
163+
// remove prefix "?" of SAS if any
164+
sasToken = Util.GetSASStringWithoutQuestionMark(sasToken);
198165

199-
if (FullUri)
200-
{
201-
string fullUri = SasTokenHelper.GetFullUriWithSASToken(container.Uri.AbsoluteUri.ToString(), sasToken);
202-
WriteObject(fullUri);
203-
}
204-
else
205-
{
206-
WriteObject(sasToken);
207-
}
166+
if (FullUri)
167+
{
168+
string fullUri = SasTokenHelper.GetFullUriWithSASToken(container.Uri.AbsoluteUri.ToString(), sasToken);
169+
WriteObject(fullUri);
170+
}
171+
else
172+
{
173+
WriteObject(sasToken);
208174
}
209175
}
210176

src/Storage/Storage/Common/AzureStorageBlob.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ public AzureStorageBlob(TaggedBlobItem blob, AzureStorageContext storageContext,
315315
Uri blobUri = uriBuilder.ToUri();
316316
if (storageContext.StorageAccount != null && storageContext.StorageAccount.Credentials != null && storageContext.StorageAccount.Credentials.IsSAS)
317317
{
318-
blobUri= new Uri(blobUri.ToString() + storageContext.StorageAccount.Credentials.SASToken);
318+
blobUri= new Uri(blobUri.ToString() + "?" + Util.GetSASStringWithoutQuestionMark(storageContext.StorageAccount.Credentials.SASToken));
319319
}
320320
this.privateBlobBaseClient = Util.GetTrack2BlobClient(blobUri, storageContext, options);
321321

src/Storage/Storage/Common/Cmdlet/NewAzureStorageAccountSasToken.cs

Lines changed: 7 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Common.Cmdlet
2323
using global::Azure.Storage;
2424
using Microsoft.WindowsAzure.Commands.Common.CustomAttributes;
2525

26-
[GenericBreakingChangeWithVersion("The leading question mark '?' of the created SAS token will be removed in a future release.", "11.0.0", "6.0.0")]
2726
[Cmdlet("New", Azure.Commands.ResourceManager.Common.AzureRMConstants.AzurePrefix + "StorageAccountSASToken"), OutputType(typeof(String))]
2827
public class NewAzureStorageAccountSasTokenCommand : StorageCloudBlobCmdletBase
2928
{
@@ -92,42 +91,18 @@ public NewAzureStorageAccountSasTokenCommand(IStorageBlobManagement channel)
9291
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
9392
public override void ExecuteCmdlet()
9493
{
95-
if (Channel != null && Channel.StorageContext != null && Channel.StorageContext.StorageAccount != null
94+
if (Channel != null && Channel.StorageContext != null && Channel.StorageContext.StorageAccount != null
9695
&& Channel.StorageContext.StorageAccount.Credentials != null && !Channel.StorageContext.StorageAccount.Credentials.IsSharedKey)
9796
{
9897
throw new ArgumentException("Storage account SAS token must be secured with the storage account key.", "Context");
9998
}
100-
if (!UseTrack2Sdk()) // Track1
101-
{
102-
var sharedAccessPolicy = new SharedAccessAccountPolicy()
103-
{
104-
Permissions = SetupAccessPolicyPermission(this.Permission),
105-
Services = Service,
106-
ResourceTypes = ResourceType,
107-
Protocols = Protocol,
108-
IPAddressOrRange = Util.SetupIPAddressOrRangeForSAS(this.IPAddressOrRange)
109-
};
110-
111-
DateTimeOffset? accessStartTime;
112-
DateTimeOffset? accessEndTime;
113-
SasTokenHelper.SetupAccessPolicyLifeTime(StartTime, ExpiryTime,
114-
out accessStartTime, out accessEndTime, true);
115-
sharedAccessPolicy.SharedAccessStartTime = accessStartTime;
116-
sharedAccessPolicy.SharedAccessExpiryTime = accessEndTime;
117-
118-
this.WriteObject(Channel.GetStorageAccountSASToken(sharedAccessPolicy));
119-
}
120-
else
121-
{
122-
AccountSasBuilder sasBuilder = SasTokenHelper.SetAccountSasBuilder(this.Service, this.ResourceType, Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol, this.EncryptionScope);
123-
string sasToken = sasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(Channel.StorageContext.StorageAccountName, Channel.StorageContext.StorageAccount.Credentials.ExportBase64EncodedKey())).ToString();
124-
if (sasToken[0] != '?')
125-
{
126-
sasToken = "?" + sasToken;
127-
}
128-
this.WriteObject(sasToken);
129-
}
99+
AccountSasBuilder sasBuilder = SasTokenHelper.SetAccountSasBuilder(this.Service, this.ResourceType, Permission, this.StartTime, this.ExpiryTime, this.IPAddressOrRange, this.Protocol, this.EncryptionScope);
100+
string sasToken = sasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(Channel.StorageContext.StorageAccountName, Channel.StorageContext.StorageAccount.Credentials.ExportBase64EncodedKey())).ToString();
101+
102+
// remove prefix "?" of SAS if any
103+
sasToken = Util.GetSASStringWithoutQuestionMark(sasToken);
130104

105+
this.WriteObject(sasToken);
131106
}
132107

133108
/// <summary>

src/Storage/Storage/Common/Cmdlet/NewAzureStorageContext.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,6 @@ public class NewAzureStorageContext : AzureDataCmdlet
151151
public string StorageAccountKey { get; set; }
152152

153153
private const string SasTokenHelpMessage = "Azure Storage SAS Token";
154-
[CmdletParameterBreakingChangeWithVersion("SasToken", "11.0.0", "6.0.0", ChangeDescription = "The SAS token in created Storage context properties " +
155-
"'ConnectionString' and 'StorageAccount.Credentials' won't have the leading question mark '?' in a future release.")]
156154
[Parameter(HelpMessage = SasTokenHelpMessage,
157155
Mandatory = true, ParameterSetName = SasTokenParameterSet)]
158156
[Parameter(HelpMessage = SasTokenHelpMessage,

src/Storage/Storage/Common/SasTokenHelper.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,17 +237,18 @@ public static void SetupAccessPolicyLifeTime(DateTime? startTime, DateTime? expi
237237
}
238238

239239
public static string GetFullUriWithSASToken(string absoluteUri, string sasToken)
240-
{
240+
{
241+
// make sure sas token not contains prefix "?"
242+
sasToken = Util.GetSASStringWithoutQuestionMark(sasToken);
241243

242244
if (absoluteUri.Contains("?"))
243245
{
244-
// There is already a query string in the URI,
245-
// remove "?" from sas token.
246-
return absoluteUri + "&" + sasToken.Substring(1);
246+
// There is already a query string in the URI, so just append sas
247+
return absoluteUri + "&" + sasToken;
247248
}
248249
else
249250
{
250-
return absoluteUri + sasToken;
251+
return absoluteUri + "?" + sasToken;
251252
}
252253
}
253254

0 commit comments

Comments
 (0)