Skip to content

Commit

Permalink
[Storage] Support localuser nfsv3 (#25780)
Browse files Browse the repository at this point in the history
* [Storage] Support localuser nfsv3

* remove suffix s from parameter name
  • Loading branch information
blueww authored Aug 8, 2024
1 parent 73374d0 commit 23c384f
Show file tree
Hide file tree
Showing 14 changed files with 1,786 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,13 @@ public void TestAzureStorageLocalUserSftp()
TestRunner.RunTestScript("Test-AzureStorageLocalUserSftp");
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void TestAzureStorageLocalUserNFSV3()
{
TestRunner.RunTestScript("Test-AzureStorageLocalUserNFSV3");
}

[Fact]
[Trait(Category.AcceptanceType, Category.CheckIn)]
public void TestStorageAccountAllowedCopyScope()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2441,6 +2441,96 @@ function Test-AzureStorageLocalUserSftp
}
}


<#
.SYNOPSIS
Test AzureStorageLocalUserNFSV3
.DESCRIPTION
SmokeTest
#>
function Test-AzureStorageLocalUserNFSV3
{
# Setup
$rgname = Get-StorageManagementTestResourceName;

try
{
# Test
$stoname = 'sto' + $rgname;
$stotype = 'Standard_LRS';
$loc = Get-ProviderLocation_Canary ResourceManagement;
$kind = 'StorageV2'

New-AzResourceGroup -Name $rgname -Location $loc;
New-AzStorageAccount -ResourceGroupName $rgname -Name $stoname -Location $loc -Type $stotype -Kind $kind -EnableSftp $true -EnableHierarchicalNamespace $true -EnableNfsV3 $true -EnableLocalUser $true `
-EnableExtendedGroup $true -NetworkRuleSet (@{bypass="AzureServices";defaultAction="deny"})

Retry-IfException { $global:sto = Get-AzStorageAccount -ResourceGroupName $rgname -Name $stoname; }
Assert-AreEqual $stoname $sto.StorageAccountName;
Assert-AreEqual $stotype $sto.Sku.Name;
Assert-AreEqual $loc.ToLower().Replace(" ", "") $sto.Location;
Assert-AreEqual $kind $sto.Kind;
Assert-AreEqual $true $sto.EnableSftp;
Assert-AreEqual $true $sto.EnableNfsV3;
Assert-AreEqual $true $sto.EnableLocalUser;
Assert-AreEqual $true $sto.EnableExtendedGroups;

Retry-IfException { $global:sto = Set-AzStorageAccount -ResourceGroupName $rgname -Name $stoname -EnableExtendedGroup $false }
Assert-AreEqual $false $sto.EnableExtendedGroups;

Retry-IfException { $global:sto = Set-AzStorageAccount -ResourceGroupName $rgname -Name $stoname -EnableExtendedGroup $true }
Assert-AreEqual $true $sto.EnableExtendedGroups;

# create local user
$userName1 = "nfsv3_70005"
$localuser1 = Set-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname -UserName $userName1 -HomeDirectory /test -IsNfSv3Enabled $true -ExtendedGroup 1,2,3,4,5
Assert-AreEqual $userName1 $localuser1.Name;
Assert-AreEqual "/test" $localuser1.HomeDirectory;
Assert-AreEqual 5 $localuser1.ExtendedGroups.Count;
Assert-AreEqual $true $localuser1.IsNfSv3Enabled;

$userName2 = "testuser2"
$localuser2 = Set-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname -UserName $userName2 -HomeDirectory "/dir1"
Assert-AreEqual $userName2 $localuser2.Name;
Assert-Null $localuser2.HasSharedKey;
Assert-Null $localuser2.HasSshKey;
Assert-Null $localuser2.HasSshPassword;
Assert-AreEqual "/dir1" $localuser2.HomeDirectory;
Assert-Null $localuser2.PermissionScopes;
Assert-Null $localuser2.SshAuthorizedKeys;

# update local user
$localuser1 = Set-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname -UserName $userName1 -HomeDirectory /test -ExtendedGroup 1,2,3
Assert-AreEqual $userName1 $localuser1.Name;
Assert-AreEqual "/test" $localuser1.HomeDirectory;
Assert-AreEqual 3 $localuser1.ExtendedGroups.Count;

#list all nfsv3 local users
$localusers = Get-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname -IncludeNFSv3
Assert-AreEqual 1 $localusers.Count;
Assert-AreEqual $userName1 $localusers[0].Name;

#list all none-nfsv3 local users
$localusers = Get-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname
Assert-AreEqual 1 $localusers.Count;
Assert-AreEqual $userName2 $localusers[0].Name;

# remove local user
Remove-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname -UserName $userName1
$localusers = Get-AzStorageLocalUser -ResourceGroupName $rgname -StorageAccountName $stoname
Assert-AreEqual 1 $localusers.Count;
Assert-AreEqual $userName2 $localusers[0].Name;

#clean up
Remove-AzStorageAccount -Force -ResourceGroupName $rgname -Name $stoname;
}
finally
{
# Cleanup
Clean-ResourceGroup $rgname
}
}

<#
.SYNOPSIS
Test Test-StorageAccountAllowedCopyScope
Expand Down

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/Storage/Storage.Management/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
- Additional information about change #1
-->
## Upcoming Release
* Supported local user IsNfSv3Enabled and ExtendedGroup
- `Set-AzStorageLocalUser`
* Supported list local user with IncludeNFSv3
- `Get-AzStorageLocalUser`
* Supported EnableExtendedGroup when creating and updating a storage account
- `New-AzStorageAccount`
- `Set-AzStorageAccount`

## Version 7.2.0
* Upgraded Microsoft.Azure.Storage.DataMovement to 2.0.5
Expand Down
9 changes: 8 additions & 1 deletion src/Storage/Storage.Management/Models/PSLocalUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.Azure.Management.Storage.Models;
using Microsoft.WindowsAzure.Commands.Common.Attributes;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.Azure.Commands.Management.Storage.Models
{
Expand All @@ -38,7 +39,9 @@ public PSLocalUser(LocalUser user, string ResourceGroupName, string StorageAccou
this.HasSshKey = user.HasSshKey;
this.HasSshPassword = user.HasSshPassword;
this.SshAuthorizedKeys = PSSshPublicKey.GetPSSshPublicKeys(user.SshAuthorizedKeys);
this.PermissionScopes = PSPermissionScope.GetPSPermissionScopes(user.PermissionScopes);
this.PermissionScopes = PSPermissionScope.GetPSPermissionScopes(user.PermissionScopes);
this.IsNfSv3Enabled = user.IsNfSv3Enabled;
this.ExtendedGroups = user.ExtendedGroups == null ? null : user.ExtendedGroups.ToArray();
this.GroupId = user.GroupId;
this.AllowAclAuthorization = user.AllowAclAuthorization;
this.UserId = user.UserId;
Expand All @@ -55,6 +58,8 @@ public LocalUser ParseLocalUser()
user.HasSshPassword = this.HasSshPassword;
user.SshAuthorizedKeys = PSSshPublicKey.ParseSshPublicKeyss(this.SshAuthorizedKeys);
user.PermissionScopes = PSPermissionScope.ParsePermissionScopes(this.PermissionScopes);
user.IsNfSv3Enabled = this.IsNfSv3Enabled;
user.ExtendedGroups = this.ExtendedGroups is null ? null : new List<int?>(this.ExtendedGroups);
user.GroupId = this.GroupId;
user.AllowAclAuthorization = this.AllowAclAuthorization;
return user;
Expand Down Expand Up @@ -82,6 +87,8 @@ public LocalUser ParseLocalUser()
public bool? HasSshPassword { get; set; }
public PSSshPublicKey[] SshAuthorizedKeys { get; set; }
public PSPermissionScope[] PermissionScopes { get; set; }
public int?[] ExtendedGroups { get; set; }
public bool? IsNfSv3Enabled { get; set; }
public int? GroupId { get; set; }
public bool? AllowAclAuthorization { get; set; }
public int? UserId { get; set; }
Expand Down
2 changes: 2 additions & 0 deletions src/Storage/Storage.Management/Models/PSStorageAccount.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ public PSStorageAccount(StorageModels.StorageAccount storageAccount)
this.EnableLocalUser = storageAccount.IsLocalUserEnabled;
this.AllowedCopyScope = storageAccount.AllowedCopyScope;
this.DnsEndpointType = storageAccount.DnsEndpointType;
this.EnableExtendedGroups = storageAccount.EnableExtendedGroups;
}
public bool? AllowCrossTenantReplication { get; set; }

Expand Down Expand Up @@ -170,6 +171,7 @@ public PSStorageAccount(StorageModels.StorageAccount storageAccount)
public PSImmutableStorageAccount ImmutableStorageWithVersioning { get; set; }
public PSStorageAccountSkuConversionStatus StorageAccountSkuConversionStatus { get; set; }
public string DnsEndpointType { get; set; }
public bool? EnableExtendedGroups { get; set; }

public static PSStorageAccount Create(StorageModels.StorageAccount storageAccount, IStorageManagementClient client)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public class GetAzureStorageLocalUserCommand : StorageFileBaseCmdlet
HelpMessage = "The name of local user. The username must contain lowercase letters and numbers only. It must be unique only within the storage account.")]
[ValidateNotNullOrEmpty]
public string UserName { get; set; }

[Parameter(Mandatory = false,
HelpMessage = "The maximum number of local users that will be included in the list response")]
[ValidateNotNullOrEmpty]
Expand All @@ -71,7 +71,11 @@ public class GetAzureStorageLocalUserCommand : StorageFileBaseCmdlet
HelpMessage = "The filter of username. When specified, only usernames starting with the filter will be listed. The filter must be in format: startswith(name, <prefix>)")]
[ValidateNotNullOrEmpty]
public string Filter { get; set; }


[Parameter(Mandatory = false,
HelpMessage = "Specify to include NFSv3 enabled Local Users in list Local Users.")]
[ValidateNotNullOrEmpty]
public SwitchParameter IncludeNFSv3 { get; set; }

public override void ExecuteCmdlet()
{
Expand All @@ -92,8 +96,9 @@ public override void ExecuteCmdlet()
{
var users = this.StorageClient.LocalUsers.List(
this.ResourceGroupName,
this.StorageAccountName, this.MaxPageSize, this.Filter);

this.StorageAccountName, this.MaxPageSize, this.Filter,
include: this.IncludeNFSv3.IsPresent ? "nfsv3" : null);

if (users != null)
{
foreach(LocalUser localUser in users)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,23 @@ public bool EnableLocalUser
}
private bool? enableLocalUser = null;

[Parameter(
Mandatory = false,
HelpMessage = "Enables extended group support with local users feature, if set to true.")]
[ValidateNotNullOrEmpty]
public bool EnableExtendedGroup
{
get
{
return enableExtendedGroup != null ? enableExtendedGroup.Value : false;
}
set
{
enableExtendedGroup = value;
}
}
private bool? enableExtendedGroup = null;

[Parameter(
Mandatory = false,
HelpMessage = "Enable HierarchicalNamespace for the Storage account.")]
Expand Down Expand Up @@ -915,6 +932,10 @@ public override void ExecuteCmdlet()
{
createParameters.IsLocalUserEnabled = this.enableLocalUser;
}
if (this.enableExtendedGroup != null)
{
createParameters.EnableExtendedGroups = this.enableExtendedGroup;
}
if (this.AllowedCopyScope != null)
{
createParameters.AllowedCopyScope = this.AllowedCopyScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,23 @@ public bool EnableLocalUser
}
private bool? enableLocalUser = null;

[Parameter(
Mandatory = false,
HelpMessage = "Enables extended group support with local users feature, if set to true.")]
[ValidateNotNullOrEmpty]
public bool EnableExtendedGroup
{
get
{
return enableExtendedGroup != null ? enableExtendedGroup.Value : false;
}
set
{
enableExtendedGroup = value;
}
}
private bool? enableExtendedGroup = null;

[Parameter(Mandatory = false, HelpMessage = "Set restrict copy to and from Storage Accounts within a Microsoft Entra tenant or with Private Links to the same VNet. Possible values include: 'PrivateLink', 'AAD'")]
[PSArgumentCompleter("PrivateLink", "AAD")]
[ValidateNotNullOrEmpty]
Expand Down Expand Up @@ -927,6 +944,10 @@ public override void ExecuteCmdlet()
{
updateParameters.IsLocalUserEnabled = this.enableLocalUser;
}
if (this.enableExtendedGroup != null)
{
updateParameters.EnableExtendedGroups = this.enableExtendedGroup;
}
if (this.AllowedCopyScope != null)
{
updateParameters.AllowedCopyScope = this.AllowedCopyScope;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using Microsoft.Azure.Commands.Management.Storage.Models;
using Microsoft.Azure.Management.Storage;
using Microsoft.Azure.Management.Storage.Models;
using System.Linq;
using System.Management.Automation;

namespace Microsoft.Azure.Commands.Management.Storage
Expand Down Expand Up @@ -140,10 +141,32 @@ public bool HasSshPassword
[ValidateNotNullOrEmpty]
public bool? AllowAclAuthorization { get; set; }

[Parameter(
Mandatory = false,
HelpMessage = "Indicates whether LocalUser belongs to NFSv3 or SFTP.")]
[ValidateNotNullOrEmpty]
public bool IsNfSv3Enabled
{
get
{
return isNfSv3Enabled != null ? isNfSv3Enabled.Value : false;
}
set
{
isNfSv3Enabled = value;
}
}
private bool? isNfSv3Enabled = null;

[Parameter(Mandatory = false,
HelpMessage = "Sets extended Groups of which user is part of, only for NFSv3 User.")]
[ValidateNotNullOrEmpty]
public int[] ExtendedGroup { get; set; }

public override void ExecuteCmdlet()
{
base.ExecuteCmdlet();

if (ShouldProcess(this.UserName, "Create Storage Account LocalUser with name:"))
{
switch (ParameterSetName)
Expand All @@ -165,17 +188,40 @@ public override void ExecuteCmdlet()
HasSshPassword = this.hasSshPassword,
PermissionScopes = this.PermissionScope,
SshAuthorizedKeys = this.SshAuthorizedKey,
IsNfSv3Enabled = this.isNfSv3Enabled,
ExtendedGroups = this.ExtendedGroup is null ? null : this.ExtendedGroup.Cast<int?>().ToArray(),
GroupId = this.GroupId,
AllowAclAuthorization = this.AllowAclAuthorization,
};

LocalUser localUser = this.StorageClient.LocalUsers.CreateOrUpdate(
this.ResourceGroupName,
this.StorageAccountName,
this.UserName,
localuser.ParseLocalUser());
try
{
LocalUser localUser = this.StorageClient.LocalUsers.CreateOrUpdate(
this.ResourceGroupName,
this.StorageAccountName,
this.UserName,
localuser.ParseLocalUser());

WriteObject(new PSLocalUser(localUser, this.ResourceGroupName, this.StorageAccountName));
}

WriteObject(new PSLocalUser(localUser, this.ResourceGroupName, this.StorageAccountName));
catch (ErrorResponseException e)
{
if (e.Body != null && e.Body.Error != null && e.Body.Error.Message != null)
{
// sdk will not add the detail error message to exception message for custmized error, so create a new exception with detail error in exception message
ErrorResponseException newex = new ErrorResponseException(e.Body.Error.Message, e);
newex.Request = e.Request;
newex.Response = e.Response;
newex.Source = e.Source;
newex.Body = e.Body;
throw newex;
}
else
{
throw e;
}
}
}
}
}
Expand Down
Loading

0 comments on commit 23c384f

Please sign in to comment.