diff --git a/src/Storage/Storage.Management.Test/ScenarioTests/StorageDataPlaneTests.ps1 b/src/Storage/Storage.Management.Test/ScenarioTests/StorageDataPlaneTests.ps1 index 3e2369a4aff6..d7252b63868e 100644 --- a/src/Storage/Storage.Management.Test/ScenarioTests/StorageDataPlaneTests.ps1 +++ b/src/Storage/Storage.Management.Test/ScenarioTests/StorageDataPlaneTests.ps1 @@ -846,7 +846,9 @@ function Test-DatalakeGen2 -Permission rw-rw--wx ` -Owner '$superuser' ` -Group '$superuser' - $file1 = Get-AzDataLakeGen2Item -Context $storageContext -FileSystem $filesystemName -Path $filePath1 + $sas = New-AzDataLakeGen2SasToken -FileSystem $filesystemName -Path $filePath1 -Permission rw -Context $storageContext + $ctxsas = New-AzStorageContext -StorageAccountName $StorageAccountName -SasToken $sas + $file1 = Get-AzDataLakeGen2Item -Context $ctxsas -FileSystem $filesystemName -Path $filePath1 Assert-AreEqual $file1.Path $filePath1 Assert-AreEqual $file1.Permissions.ToSymbolicPermissions() "rw-rw--wx" Assert-AreEqual $file1.Properties.ContentType $ContentType diff --git a/src/Storage/Storage.Management.Test/Storage.Management.Test.csproj b/src/Storage/Storage.Management.Test/Storage.Management.Test.csproj index 233191c0a2da..e487d11b89d4 100644 --- a/src/Storage/Storage.Management.Test/Storage.Management.Test.csproj +++ b/src/Storage/Storage.Management.Test/Storage.Management.Test.csproj @@ -11,10 +11,10 @@ - - - - + + + + diff --git a/src/Storage/Storage.Management/Az.Storage.psd1 b/src/Storage/Storage.Management/Az.Storage.psd1 index 52f8009a93ae..927a80e6d27e 100644 --- a/src/Storage/Storage.Management/Az.Storage.psd1 +++ b/src/Storage/Storage.Management/Az.Storage.psd1 @@ -197,7 +197,8 @@ CmdletsToExport = 'Get-AzStorageAccount', 'Get-AzStorageAccountKey', 'Set-AzStorageBlobImmutabilityPolicy', 'Remove-AzStorageBlobImmutabilityPolicy', 'Set-AzStorageBlobLegalHold', - 'Invoke-AzRmStorageContainerImmutableStorageWithVersioningMigration' + 'Invoke-AzRmStorageContainerImmutableStorageWithVersioningMigration', + 'New-AzDataLakeGen2SasToken' # Variables to export from this module # VariablesToExport = @() diff --git a/src/Storage/Storage.Management/ChangeLog.md b/src/Storage/Storage.Management/ChangeLog.md index 6cd4ab3ce0f3..ce052da251fe 100644 --- a/src/Storage/Storage.Management/ChangeLog.md +++ b/src/Storage/Storage.Management/ChangeLog.md @@ -18,6 +18,8 @@ - Additional information about change #1 --> ## Upcoming Release +* Supported generae Sas token for DataLakeGen2 + - `New-AzDataLakeGen2SasToken` * Show OAuth token in debug log in debug build only - `New-AzStorageContext` diff --git a/src/Storage/Storage.Management/help/Az.Storage.md b/src/Storage/Storage.Management/help/Az.Storage.md index be52c90c40f6..61baa0b35d88 100644 --- a/src/Storage/Storage.Management/help/Az.Storage.md +++ b/src/Storage/Storage.Management/help/Az.Storage.md @@ -197,6 +197,9 @@ Move a file or directory to another a file or directory in same Storage account. ### [New-AzDataLakeGen2Item](New-AzDataLakeGen2Item.md) Create a file or directory in a filesystem. +### [New-AzDataLakeGen2SasToken](New-AzDataLakeGen2SasToken.md) +Generates a SAS token for an Azure storage blob. + ### [New-AzRmStorageContainer](New-AzRmStorageContainer.md) Creates a Storage blob container diff --git a/src/Storage/Storage.Management/help/New-AzDataLakeGen2SasToken.md b/src/Storage/Storage.Management/help/New-AzDataLakeGen2SasToken.md new file mode 100644 index 000000000000..15d3be3a4281 --- /dev/null +++ b/src/Storage/Storage.Management/help/New-AzDataLakeGen2SasToken.md @@ -0,0 +1,238 @@ +--- +external help file: Microsoft.Azure.PowerShell.Cmdlets.Storage.dll-Help.xml +Module Name: Az.Storage +online version: https://docs.microsoft.com/powershell/module/az.storage/new-azdatalakegen2sastoken +schema: 2.0.0 +--- + +# New-AzDataLakeGen2SasToken + +## SYNOPSIS +Generates a SAS token for Azure DatalakeGen2 item. + +## SYNTAX + +### ReceiveManual (Default) +``` +New-AzDataLakeGen2SasToken [-FileSystem] [-Path ] [-Permission ] + [-Protocol ] [-IPAddressOrRange ] [-StartTime ] + [-ExpiryTime ] [-FullUri] [-Context ] + [-DefaultProfile ] [] +``` + +### ItemPipeline +``` +New-AzDataLakeGen2SasToken -InputObject [-Permission ] + [-Protocol ] [-IPAddressOrRange ] [-StartTime ] + [-ExpiryTime ] [-FullUri] [-Context ] + [-DefaultProfile ] [] +``` + +## DESCRIPTION +The **New-AzDataLakeGen2SasToken** cmdlet generates a Shared Access Signature (SAS) token for an Azure DatalakeGen2 item. + +## EXAMPLES + +### Example 1: Generate a SAS token with full permission +``` +New-AzDataLakeGen2SasToken -FileSystem "filesystem1" -Path "dir1/dir2" -Permission racwdlmeop +``` + +This example generates a DatalakeGen2 SAS token with full permission. + +### Example 2: Generate a SAS token with specific StartTime, ExpireTime, Protocal, IPAddressOrRange, by pipeline a datalakegen2 item +``` +Get-AzDataLakeGen2Item -FileSystem test -Path "testdir/dir2" | New-AzDataLakeGen2SasToken -Permission rw -Protocol Https -IPAddressOrRange 10.0.0.0-12.10.0.0 -StartTime (Get-Date) -ExpiryTime (Get-Date).AddDays(6) +``` + +This example generates a DatalakeGen2 SAS token by pipeline a datalake gen2 item, and with specific StartTime, ExpireTime, Protocal, IPAddressOrRange. + +## PARAMETERS + +### -Context +Azure Storage Context Object + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.IStorageContext +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName, ByValue) +Accept wildcard characters: False +``` + +### -DefaultProfile +The credentials, account, tenant, and subscription used for communication with Azure. + +```yaml +Type: Microsoft.Azure.Commands.Common.Authentication.Abstractions.Core.IAzureContextContainer +Parameter Sets: (All) +Aliases: AzureRmContext, AzureCredential + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -ExpiryTime +Expiry Time + +```yaml +Type: System.Nullable`1[System.DateTimeOffset] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -FileSystem +FileSystem name + +```yaml +Type: System.String +Parameter Sets: ReceiveManual +Aliases: + +Required: True +Position: 0 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -FullUri +Display full uri with sas token + +```yaml +Type: System.Management.Automation.SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -InputObject +Azure Datalake Gen2 Item Object to remove. + +```yaml +Type: Microsoft.WindowsAzure.Commands.Common.Storage.ResourceModel.AzureDataLakeGen2Item +Parameter Sets: ItemPipeline +Aliases: + +Required: True +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -IPAddressOrRange +IP, or IP range ACL (access control list) that the request would be accepted by Azure Storage. + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Path +The path in the specified FileSystem that should be retrieved. +Can be a file or directory In the format 'directory/file.txt' or 'directory1/directory2/'. +Skip set this parameter to get the root directory of the Filesystem. + +```yaml +Type: System.String +Parameter Sets: ReceiveManual +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -Permission +Permissions for a blob. +Permissions can be any not-empty subset of "racwdlmeop". + +```yaml +Type: System.String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Protocol +Protocol can be used in the request with this SAS token. + +```yaml +Type: System.Nullable`1[Azure.Storage.Sas.SasProtocol] +Parameter Sets: (All) +Aliases: +Accepted values: None, HttpsAndHttp, Https + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -StartTime +Start Time + +```yaml +Type: System.Nullable`1[System.DateTimeOffset] +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### System.String + +### Microsoft.WindowsAzure.Commands.Common.Storage.ResourceModel.AzureDataLakeGen2Item + +### Microsoft.Azure.Commands.Common.Authentication.Abstractions.IStorageContext + +## OUTPUTS + +### System.String + +## NOTES + +## RELATED LINKS diff --git a/src/Storage/Storage/Blob/StorageCloudBlobCmdletBase.cs b/src/Storage/Storage/Blob/StorageCloudBlobCmdletBase.cs index c04b2b703cf2..9228a4f47fd2 100644 --- a/src/Storage/Storage/Blob/StorageCloudBlobCmdletBase.cs +++ b/src/Storage/Storage/Blob/StorageCloudBlobCmdletBase.cs @@ -74,6 +74,24 @@ public BlobRequestOptions RequestOptions } } + public DataLakeClientOptions DataLakeClientOptions + { + get + { + if (dataLakeClientOptions == null) + { + dataLakeClientOptions = new DataLakeClientOptions(); + dataLakeClientOptions.AddPolicy(new UserAgentPolicy(ApiConstants.UserAgentHeaderValue), HttpPipelinePosition.PerCall); + return dataLakeClientOptions; + } + else + { + return dataLakeClientOptions; + } + } + } + private DataLakeClientOptions dataLakeClientOptions = null; + public BlobClientOptions ClientOptions { get @@ -664,20 +682,20 @@ internal DataLakeFileSystemClient GetFileSystemClientByName(IStorageBlobManageme if (localChannel.StorageContext.StorageAccount.Credentials.IsToken) //Oauth { - fileSystem = new DataLakeFileSystemClient(fileSystemUri, localChannel.StorageContext.Track2OauthToken); + fileSystem = new DataLakeFileSystemClient(fileSystemUri, localChannel.StorageContext.Track2OauthToken, this.DataLakeClientOptions); } else if (localChannel.StorageContext.StorageAccount.Credentials.IsSAS) //SAS { - fileSystem = new DataLakeFileSystemClient(new Uri (fileSystemUri.ToString() + "?" + Util.GetSASStringWithoutQuestionMark(localChannel.StorageContext.StorageAccount.Credentials.SASToken))); + fileSystem = new DataLakeFileSystemClient(new Uri (fileSystemUri.ToString() + "?" + Util.GetSASStringWithoutQuestionMark(localChannel.StorageContext.StorageAccount.Credentials.SASToken)), this.DataLakeClientOptions); } else if (localChannel.StorageContext.StorageAccount.Credentials.IsSharedKey) //Shared Key { fileSystem = new DataLakeFileSystemClient(fileSystemUri, - new StorageSharedKeyCredential(localChannel.StorageContext.StorageAccountName, localChannel.StorageContext.StorageAccount.Credentials.ExportBase64EncodedKey())); + new StorageSharedKeyCredential(localChannel.StorageContext.StorageAccountName, localChannel.StorageContext.StorageAccount.Credentials.ExportBase64EncodedKey()), this.DataLakeClientOptions); } else //Anonymous { - fileSystem = new DataLakeFileSystemClient(fileSystemUri); + fileSystem = new DataLakeFileSystemClient(fileSystemUri, this.DataLakeClientOptions); } return fileSystem; diff --git a/src/Storage/Storage/Common/AzureDataLakeGen2Item.cs b/src/Storage/Storage/Common/AzureDataLakeGen2Item.cs index b5c0e281e904..77b01eff2b94 100644 --- a/src/Storage/Storage/Common/AzureDataLakeGen2Item.cs +++ b/src/Storage/Storage/Common/AzureDataLakeGen2Item.cs @@ -103,6 +103,11 @@ public class AzureDataLakeGen2Item : AzureStorageBase [Ps1Xml(Label = "Group", Target = ViewControl.Table, Position = 7, TableColumnWidth = 10)] public string Group { get; set; } + /// + /// The PathItem properties of the item, the property only exist if the item is listout + /// + public PathItem ListPathItem { get; set; } + /// /// Azure DataLakeGen2 Item constructor /// @@ -190,6 +195,7 @@ public AzureDataLakeGen2Item(PathItem item, DataLakeFileSystemClient fileSystem, { this.Name = item.Name; this.Path = item.Name; + this.ListPathItem = item; this.IsDirectory = item.IsDirectory is null ? false : item.IsDirectory.Value; DataLakePathClient pathclient = null; if (this.IsDirectory) // Directory diff --git a/src/Storage/Storage/Common/SasTokenHelper.cs b/src/Storage/Storage/Common/SasTokenHelper.cs index ad96a7fd0b19..eac2e962f7dd 100644 --- a/src/Storage/Storage/Common/SasTokenHelper.cs +++ b/src/Storage/Storage/Common/SasTokenHelper.cs @@ -29,6 +29,7 @@ namespace Microsoft.WindowsAzure.Commands.Storage.Common using System.Threading; using global::Azure.Storage.Blobs; using global::Azure.Storage; + using global::Azure.Storage.Files.DataLake; internal class SasTokenHelper { @@ -504,6 +505,35 @@ public static string GetBlobSharedAccessSignature(AzureStorageContext context, B } } + /// + /// Get SAS string for DatalakeGen2 + /// + public static string GetDatalakeGen2SharedAccessSignature(AzureStorageContext context, DataLakeSasBuilder sasBuilder, bool generateUserDelegationSas, DataLakeClientOptions clientOptions, CancellationToken cancelToken) + { + if (context != null && context.StorageAccount.Credentials.IsSharedKey) + { + return sasBuilder.ToSasQueryParameters(new StorageSharedKeyCredential(context.StorageAccountName, context.StorageAccount.Credentials.ExportBase64EncodedKey())).ToString(); + } + if (generateUserDelegationSas) + { + global::Azure.Storage.Files.DataLake.Models.UserDelegationKey userDelegationKey = null; + DataLakeServiceClient oauthService = new DataLakeServiceClient(context.StorageAccount.BlobEndpoint, context.Track2OauthToken, clientOptions); + + Util.ValidateUserDelegationKeyStartEndTime(sasBuilder.StartsOn, sasBuilder.ExpiresOn); + + userDelegationKey = oauthService.GetUserDelegationKey( + startsOn: sasBuilder.StartsOn == DateTimeOffset.MinValue || sasBuilder.StartsOn == null ? DateTimeOffset.UtcNow : sasBuilder.StartsOn.ToUniversalTime(), + expiresOn: sasBuilder.ExpiresOn.ToUniversalTime(), + cancellationToken: cancelToken); + + return sasBuilder.ToSasQueryParameters(userDelegationKey, context.StorageAccountName).ToString(); + } + else + { + throw new InvalidOperationException("Create SAS only supported with SharedKey or Oauth credentail."); + } + } + /// /// Create a blob SAS build from Blob Object /// diff --git a/src/Storage/Storage/DatalakeGen2/Cmdlet/NewAzDataLakeGen2SasToken.cs b/src/Storage/Storage/DatalakeGen2/Cmdlet/NewAzDataLakeGen2SasToken.cs new file mode 100644 index 000000000000..a7395a031b49 --- /dev/null +++ b/src/Storage/Storage/DatalakeGen2/Cmdlet/NewAzDataLakeGen2SasToken.cs @@ -0,0 +1,209 @@ +// ---------------------------------------------------------------------------------- +// +// Copyright Microsoft Corporation +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// ---------------------------------------------------------------------------------- + +namespace Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet +{ + using Commands.Common.Storage.ResourceModel; + using Microsoft.WindowsAzure.Commands.Storage.Common; + using Microsoft.WindowsAzure.Commands.Storage.Model.Contract; + using System.Management.Automation; + using System.Security.Permissions; + using global::Azure.Storage.Files.DataLake; + using global::Azure.Storage.Sas; + using System; + + /// + /// list azure blobs in specified azure FileSystem + /// + [Cmdlet("New", Azure.Commands.ResourceManager.Common.AzureRMConstants.AzurePrefix + "DataLakeGen2SasToken", DefaultParameterSetName = ManualParameterSet), OutputType(typeof(String))] + public class NewDataLakeGen2SasTokenCommand : StorageCloudBlobCmdletBase + { + /// + /// manually set the name parameter + /// + private const string ManualParameterSet = "ReceiveManual"; + + /// + /// File or Dir pipeline + /// + private const string ItemParameterSet = "ItemPipeline"; + + [Parameter(ValueFromPipeline = true, Position = 0, Mandatory = true, HelpMessage = "FileSystem name", ParameterSetName = ManualParameterSet)] + [ValidateNotNullOrEmpty] + public string FileSystem { get; set; } + + [Parameter(ValueFromPipeline = true, Mandatory = false, HelpMessage = + "The path in the specified FileSystem that should be retrieved. Can be a file or directory " + + "In the format 'directory/file.txt' or 'directory1/directory2/'. Skip set this parameter to get the root directory of the Filesystem.", + ParameterSetName = ManualParameterSet)] + [ValidateNotNullOrEmpty] + public string Path { get; set; } + + [Parameter(Mandatory = true, HelpMessage = "Azure Datalake Gen2 Item Object to remove.", + ValueFromPipeline = true, ParameterSetName = ItemParameterSet)] + [ValidateNotNull] + public AzureDataLakeGen2Item InputObject { get; set; } + + [Parameter( + Mandatory = false, + HelpMessage = "Permissions for a blob. Permissions can be any not-empty subset of \"racwdlmeop\".")] + [ValidateNotNullOrEmpty] + public string Permission { get; set; } + + [Parameter(Mandatory = false, HelpMessage = "Protocol can be used in the request with this SAS token.")] + [ValidateNotNull] + public SasProtocol? Protocol { get; set; } + + [Parameter(Mandatory = false, HelpMessage = "IP, or IP range ACL (access control list) that the request would be accepted by Azure Storage.")] + [ValidateNotNullOrEmpty] + public string IPAddressOrRange { get; set; } + + [Parameter(Mandatory = false, HelpMessage = "Start Time")] + [ValidateNotNull] + public DateTimeOffset? StartTime { get; set; } + + [Parameter(Mandatory = false, HelpMessage = "Expiry Time")] + [ValidateNotNull] + public DateTimeOffset? ExpiryTime { get; set; } + + [Parameter(Mandatory = false, HelpMessage = "Display full uri with sas token")] + public SwitchParameter FullUri { get; set; } + + // Overwrite the useless parameter + public override int? ConcurrentTaskCount { get; set; } + public override int? ClientTimeoutPerRequest { get; set; } + public override int? ServerTimeoutPerRequest { get; set; } + public override string TagCondition { get; set; } + + /// + /// Initializes a new instance of the GetDataLakeGen2ItemCommand class. + /// + public NewDataLakeGen2SasTokenCommand() + : this(null) + { + } + + /// + /// Initializes a new instance of the GetDataLakeGen2ItemCommand class. + /// + /// IStorageBlobManagement channel + public NewDataLakeGen2SasTokenCommand(IStorageBlobManagement channel) + { + Channel = channel; + } + + /// + /// Execute command + /// + [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] + public override void ExecuteCmdlet() + { + IStorageBlobManagement localChannel = Channel; + + // 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(this.Path, "Generate User Delegation SAS, since input Storage Context is OAuth based.")) + { + generateUserDelegationSas = true; + } + else + { + return; + } + } + + if (this.ParameterSetName == ItemParameterSet) + { + if (this.InputObject.IsDirectory) + { + this.FileSystem = this.InputObject.Directory.FileSystemName; + this.Path = this.InputObject.Directory.Path; + } + else + { + this.FileSystem = this.InputObject.File.FileSystemName; + this.Path = this.InputObject.File.Path; + } + } + + DataLakeSasBuilder sasBuilder = new DataLakeSasBuilder(); + sasBuilder.FileSystemName = this.FileSystem; + sasBuilder.Path = this.Path; + sasBuilder.SetPermissions(this.Permission, true); + if (StartTime != null) + { + sasBuilder.StartsOn = StartTime.Value.ToUniversalTime(); + } + if (ExpiryTime != null) + { + sasBuilder.ExpiresOn = 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) + { + sasBuilder.Protocol = this.Protocol.Value; + } + + DataLakeFileSystemClient fileSystem = GetFileSystemClientByName(localChannel, this.FileSystem); + + DataLakePathClient pathClient; + DataLakeFileClient fileClient; + DataLakeDirectoryClient dirClient; + if (GetExistDataLakeGen2Item(fileSystem, this.Path, out fileClient, out dirClient)) + { + // Directory + sasBuilder.IsDirectory = true; + pathClient = dirClient; + //WriteDataLakeGen2Item(localChannel, dirClient); + // sasBuilder.ToSasQueryParameters() + } + else + { + //File + sasBuilder.IsDirectory = false; + pathClient = fileClient; + //WriteDataLakeGen2Item(Channel, fileClient); + } + string sasToken = SasTokenHelper.GetDatalakeGen2SharedAccessSignature(Channel.StorageContext, sasBuilder, generateUserDelegationSas, DataLakeClientOptions, CmdletCancellationToken); + + + if (FullUri) + { + string fullUri = pathClient.Uri.ToString(); + fullUri = fullUri + "?" + sasToken; + WriteObject(fullUri); + } + else + { + WriteObject(sasToken); + } + } + } +} diff --git a/src/Storage/Storage/Storage.csproj b/src/Storage/Storage/Storage.csproj index f36e42c3eff6..40dcb9c26faa 100644 --- a/src/Storage/Storage/Storage.csproj +++ b/src/Storage/Storage/Storage.csproj @@ -13,10 +13,10 @@ - - - - + + + + diff --git a/tools/StaticAnalysis/Exceptions/Az.Storage/SignatureIssues.csv b/tools/StaticAnalysis/Exceptions/Az.Storage/SignatureIssues.csv index 8f865f943b22..08784f2a1c3e 100644 --- a/tools/StaticAnalysis/Exceptions/Az.Storage/SignatureIssues.csv +++ b/tools/StaticAnalysis/Exceptions/Az.Storage/SignatureIssues.csv @@ -71,3 +71,4 @@ "Microsoft.Azure.PowerShell.Cmdlets.Storage.Management.dll","Microsoft.Azure.Commands.Management.Storage.UpdateAzStorageFileServicePropertyCommand","Update-AzStorageFileServiceProperty","1","8410","Parameter ShareRetentionDays of cmdlet Update-AzStorageFileServiceProperty does not follow the enforced naming convention of using a singular noun for a parameter name.","Consider using a singular noun for the parameter name." "Microsoft.Azure.PowerShell.Cmdlets.Storage.Management.dll","Microsoft.Azure.Commands.Management.Storage.NewAzureStorageBlobInventoryPolicyRuleCommand","New-AzStorageBlobInventoryPolicyRule","1","8100","New-AzStorageBlobInventoryPolicyRule Does not support ShouldProcess but the cmdlet verb New indicates that it should.","Determine if the cmdlet should implement ShouldProcess and if so determine if it should implement Force / ShouldContinue" "Microsoft.Azure.PowerShell.Cmdlets.Storage.Management.dll","Microsoft.Azure.Commands.Management.Storage.EnableAzStorageContainerDeleteRetentionPolicyCommand","Enable-AzStorageContainerDeleteRetentionPolicy","1","8410","Parameter RetentionDays of cmdlet Enable-AzStorageContainerDeleteRetentionPolicy does not follow the enforced naming convention of using a singular noun for a parameter name.","Consider using a singular noun for the parameter name." +"Az.Storage","Microsoft.WindowsAzure.Commands.Storage.Blob.Cmdlet.NewDataLakeGen2SasTokenCommand","New-AzDataLakeGen2SasToken","1","8100","New-AzDataLakeGen2SasToken Does not support ShouldProcess but the cmdlet verb New indicates that it should.","Determine if the cmdlet should implement ShouldProcess and if so determine if it should implement Force / ShouldContinue"