The NetApp Community is moving to a new platform and is in Read-Only mode. Click to learn more.
Stay connected during the transition - Join our Discord community today.

PowerShell Discussions

PowerShell Toolkit stopped working to create shares and cant figure out why

JBrendan101
191 Views

We are running 9.16.1p9 and recently turned off HTTP and HTTPS access to our SVM (recently turned only HTTPS back on) where we host some of our homedrives.  This is where the powershell toolkit script is pointed.  The SVM has a role that only allows certain behaviors 

 

API Access level

DEFAULTNone
versionRead-only
volume createRead-only
volume modifyRead-only
volume showRead-only
vserver cifs share access-control createRead/write
vserver cifs share access-control deleteRead/write
vserver cifs share access-control modifyRead/write
vserver cifs share access-control showRead/write
vserver cifs share createRead/write
vserver cifs share deleteRead/write
vserver cifs share modifyRead/write
vserver cifs share show

Read/write

When we have allowed VSAdmin the script will run but cant tell why the role causes it to fail

 

the script itself (sanitized for posting purposes) is 

 

      #F U N C T I O N S

 

      function Get_NetApp1_Folder_Array()

      {

            $Folders = @()

            $Folders = "\NetApp01$\Users"

            Return $Folders

 

            Return $Folders

      }

   

       

      function Get_NetApp2_Folder_Array()

      {

            $Folders = @()

            $Folders = "\netapp01$\Users", "\netapp02$\Users", `

                    "\netapp03$\Users"

 

            Return $Folders

      }

   

      function Get_NetApp3_Folder_Array()

      {

            $Folders = @()

            $Folders = "\netapp01$\Users", "\netapp02$\Users", `

                    "\netapp03$\Users", "\netapp04$\Users", `

                    "\netapp05$\Users"

 

            Return $Folders

      }

   

    function Get_NetApp4_Folder_Array()

      {

            $Folders = @()

            $Folders = "\netapp01$\Users","\netapp02$\Users", `

                    "\netapp03$\Users", "\netapp04$\Users", `

                    "\netapp05$\Users", "\netapp06$\Users", `

                    "\netapp07$\Users"

 

            Return $Folders

      }

   

   

      function Get_Device_Volumes ($Device)

      {

        $User = "DOMAIN\SERVICEACCOUNT"

        $Password = "SERVICEACCOUNT-PASSWORD"

 

        $SecurePass = ConvertTo-SecureString -String $Password -AsPlainText -Force

        $Credential = New-Object System.Management.Automation.PSCredential $User, $SecurePass

 

        $nacontroller = Connect-NcController $Device -HTTPS -Credential $Credential

         $VolumeNameArray = Get-NcVol -Controller $nacontroller

            Return $VolumeNameArray

      }

 

      function Test_For_User_Folder ($FolderPath2Use)

      {

            $FolderMessage = Test-Path $FolderPath2Use

            Return $FolderMessage

      }

   

      function Create_User_Folder ($FolderPath2Use)

      {

            Try

            {

                  New-Item -ItemType directory -Path $FolderPath2Use -ea Stop

                  $ReturnMessage = "The folder was created successfully."

            }

            Catch

            {

                  $ErrorMessage = $_.Exception.Message

                  $ReturnMessage = "ERROR " + $ErrorMessage

            Write-Host $ErrorMessage

            }

            Return $ReturnMessage    

      }

   

      function Set_Folder_Permissions_NetApp ($FolderPath2Use, $FQSNUser2Use)

      {

            $ACL = Get-ACL $FolderPath2Use                          # Get the existing security members

   

            $permission = $UserFQDN,"Modify","ContainerInherit,ObjectInherit","None","Allow"        

            $accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission

            

        $acl.SetAccessRule($accessRule)

 

            Try

            {

                  $acl | Set-Acl $FolderPath2Use -ea Stop

                  $ReturnMessage = "Permissions set for user " + $FQSNUser2Use + " on " + $FolderPath2Use

            }

            Catch

            {

                  $ErrorMessage = $_.Exception.Message

                  $ReturnMessage = "ERROR " + $ErrorMessage

            }

            Return $ReturnMessage

      }

 

      function Share_Folder_NetApp ($Volume2Use, $Share2Use, $Controller2Use)

      {

            $ShareMessage = ""

            $FailedToConnect = "False"

   

            Try

            {

                  $User = "DOMAIN\SERVICEACCOUNT"

                  $Password = "SERVICEACCOUNT-PASSWORD"

 

            $SecurePass = ConvertTo-SecureString -String $Password -AsPlainText -Force

            $Credential = New-Object System.Management.Automation.PSCredential $User, $SecurePass

 

            $Controller = Connect-NcController $Controller2Use -Credential $Credential -Transient:$true -ea Stop

            $FailedToConnect = "False"

            }

            Catch

            {

                  $ErrorMessage = $_.Exception.Message

                  $FailedToConnect = "True"

                  $ReturnMessage = "ERROR " + $ErrorMessage

            }

 

 

        if ($FailedToConnect -eq "False")

            {

            Try

                  {

                Add-NcCifsShare -name $Share2Use -Path $Volume2Use -Controller $Controller -Comment "Home Share"

            }

                  Catch

                  {

                        $ErrorMessage = $_.Exception.Message

                        $ShareMessage = "ERROR " + $ErrorMessage

                  }

 

            Try

                  {

                Add-NcCifsShareAcl -Share $Share2Use -UserOrGroup "Authenticated Users"  -Permission full_control -Controller $Controller -ea Stop

                  }

                  Catch

                  {

                        $ErrorMessage = $_.Exception.Message

                        $ShareMessage = "ERROR " + $ErrorMessage

                  }

 

            Try

                  {

                Set-NcCifsShareAcl -Share $Share2Use -UserOrGroup "Authenticated Users"  -Permission full_control -Controller $Controller -ea Stop

                  }

                  Catch

                  {

                        $ErrorMessage = $_.Exception.Message

                        $ShareMessage = "ERROR " + $ErrorMessage

                  }

 

            Try

                  {

                      Remove-NcCifsShareAcl -Share $Share2Use -UserOrGroup "Everyone" -Controller $Controller -ea SilentlyContinue

                  }

                  Catch

                  {

                        $ErrorMessage = $_.Exception.Message

                        $ShareMessage = "ERROR " + $ErrorMessage

                  }

            }

 

        $ShareMessage = "Share successfully created"

 

            Return $ShareMessage

      }

 

      function RemoveNTFSPermissions($path, $object, $permission)

      {

            $FileSystemRights = [System.Security.AccessControl.FileSystemRights]$permission

            $InheritanceFlag = [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit"

            $PropagationFlag = [System.Security.AccessControl.PropagationFlags]"None"

            $AccessControlType =[System.Security.AccessControl.AccessControlType]::Allow

            $Account = New-Object System.Security.Principal.NTAccount($object)

            $FileSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($Account, $FileSystemRights, $InheritanceFlag, $PropagationFlag, $AccessControlType)

            $DirectorySecurity = Get-ACL $path

            $DirectorySecurity.RemoveAccessRuleAll($FileSystemAccessRule)

            Try

        {

            Set-ACL $path -AclObject $DirectorySecurity -ErrorAction SilentlyContinue

        }

        Catch

        {

            $ErrorMessage = $_.Exception.Message

        }

      }

 

      function RemoveInheritance($path)

      {

            $isProtected = $true

            $preserveInheritance = $true

            $DirectorySecurity = Get-ACL $path

            $DirectorySecurity.SetAccessRuleProtection($isProtected, $preserveInheritance)

            Try

        {         

            Set-ACL $path -AclObject $DirectorySecurity -ErrorAction SilentlyContinue

        }

        Catch

        {

            $ErrorMessage = $_.Exception.Message

        }

      }

 

      #MAIN PROCESSING THREAD

   

    #Add values for variables from previous operation

      $HomeDrive = "\\NetApp1\JUser$"

    $HomeDrive = $HomeDrive.Trim()

 

    $SplitForUser = $HomeDrive.Replace("\\","")

    $SplitForUser = $SplitForUser.Split("\")

    $UserName = $SplitForUser[1]

    $UserName = $UserName.Replace("$","")

    $Server = $SplitForUser[0]

    $UserShare = $UserName + "$"

      $UserFQDN = "Domain\" + $UserName  

    $NetAppDevice = $Server

 

    Write-Host $UserName

   

    #Check to see if the share already exists

      #$NetAppShareExists = Test_For_User_Folder $HomeDrive

    $NetAppShareExists = $False

 

      

      if ($NetAppShareExists -eq $False)

      {

        $bOpStatus = "OK"

        $bOpMessage = "Share Good"

 

        if ($NetAppDevice -eq "NetApp1")

            {

                  $FolderArray = Get_NetApp1_Folder_Array

            }

            

            if ($NetAppDevice -eq "NetApp2")

            {

                  $FolderArray = Get_NetApp2_Folder_Array

            }

            

            if ($NetAppDevice -eq "NetApp3")

            {

                  $FolderArray = Get_NetApp3_Folder_Array

            }

            

            if ($NetAppDevice -eq "NetApp4")

            {

                  $FolderArray = Get_NetApp4_Folder_Array

            }

            

            

            $controller = $NetAppDevice

            $NetAppVolumes = Get_Device_Volumes $controller

            

            foreach ($Volume in $NetAppVolumes)

            {

                  $Check = "*" + $Volume + "*"

                    

                  foreach ($Folder in $FolderArray)

                  {

                        if ($Folder -like $Check)

                        {

                              $TotalSpace = $TotalSpace + $Volume.Available

                              $Volumes += $Volume

                        }

                  }

            }

            

            $Volumes = $Volumes | sort-object Available -descending

            

            foreach ($Folder in $FolderArray)

            {

                  $Check = "*" + $Volumes[0] + "*"

                  if ($Folder -like $Check)

                  {

                        $FolderPath = $Folder + "\"

                        $UseVolume = $Volumes[0]

                        Break

                  }

            }

            

            $PhysicalPath = "\\" + $NetAppDevice + $FolderPath + $UserName

            

        Write-Host $PhysicalPath

 

            $FolderTest = Test_For_User_Folder $PhysicalPath

        #Write-Host $PhysicalPath

            $FolderCreateMessage = ""                    

            if ($FolderTest -eq $False)

            {                    

                      $FolderCreateMessage = Create_User_Folder $PhysicalPath

            }

                                          

            if ($FolderCreateMessage -like '*ERROR*')

            {

                  $FolderCreated = "False"

                  $bOpStatus = "Failed"

                  $bOpMessage = "Could not create the user folder."

            }

            Else

            {

                  $FolderCreated = "True"

            }

 

            if ($FolderCreated -eq "True")

            {

                  $PermissionSetMessage = Set_Folder_Permissions_NetApp $PhysicalPath $UserFQDN

                                            

                  RemoveInheritance $PhysicalPath

                  RemoveNTFSPermissions $PhysicalPath "Authenticated Users" "Modify, ChangePermissions"

                  RemoveNTFSPermissions $PhysicalPath "Users" "Modify, ChangePermissions"

                  RemoveNTFSPermissions $PhysicalPath "Creator Owner" "Modify, ChangePermissions"

                  RemoveNTFSPermissions $PhysicalPath "SYSTEM" "Modify, ChangePermissions"

                                                

                  if ($PermissionSetMessage -like '*ERROR*')

                  {

                        #$PermissionSet = "True"

                $PermissionSet = "False"

                        $bOpStatus = "Failed"

                        $bOpMessage = "Unable to set folder permissions."

                  }

                  Else

                  {

                        $PermissionSet = "True"

                  }

                                          

                  If ($PermissionSet -eq "True")

                  {

                        $NetAppVolumeSharePath = "/vol/" + $UseVolume + "/Users/" + $UserName

                        $NetAppShare = $UserShare

                        $ShareCreateMessage = Share_Folder_NetApp $NetAppVolumeSharePath $NetAppShare $NetAppDevice

                        if ($ShareCreateMessage -like '*ERROR*')

                        {

                              $ShareSet = "False"

                              $bOpStatus = "Failed"

                              $bOpMessage = "Unable to share the folder."

                        }

                        Else

                        {

                              $ShareSet = "True"

                              $bOpStatus = "Completed"

                              $bOpMessage = "User Share Created."

                        }

                  }

            }

      }

      Else

      {

            $bOpStatus = "Failed"

            $bOpMessage = "User Share Already Exists."      

      }

      

      

          new-Object pscustomobject -property @{

                StatusMsg = $bOpMessage

            Status = $bOpStatus

          }

 

Any help figuring out where we have gone wrong would be amazing.  This script has worked for years and since we have started locking down more and more features we are discovering some issues.

 

Thank you in advance

 

3 REPLIES 3

mbeattie
114 Views

Hey Brendan,

 

What's the actual error message you get when running the code? Does your code work with admin privileges (IE is it a problem with your code or the RBAC role you've create)

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

mbeattie
114 Views

Hey Brendan,

 

Which version of the PSTK are you using? You can check the version using:

 

Get-NaToolKitVersion

 

I noticed in several of your functions you are using the "-HTTPS" parameter with the "Connect-NcController" CmdLet. Please note that this parameter has been deprecated and is no longer a valid parameter for newer builds of the PSTK so the attempt to connect to the cluster would fail as the parameter name is invalid. Valid parameter names are:

 

PS C:\> Get-Help Connect-NcController

NAME
    Connect-NcController

SYNOPSIS
    Connect to a clustered Data ONTAP controller.


SYNTAX
    Connect-NcController [-Name] <String[]> [-Port <UInt16>] [-Credential <PSCredential>] [-Transient] [-Vserver
    <String>] [-Timeout <Int32>] [-Add] [-ApplicationName <String>] [-SSLVersion <String>] [-InformationAction
    <ActionPreference>] [-InformationVariable <String>] [-PipelineVariable <String>] [<CommonParameters>]

 

Also from a security perspective, I would strongly recommend you don't include user names and passwords  in your code. Instead i would recommend using the "Add-NcCredential" to first cache the credentials for your RBAC user that will connect to the cluster and then from within your script use the "Get-NcCredential" to retreive the cached credential and pass the $Credential variable as an input parameter into your Function. Note that the credential can only be decrypted as the user who encrypted it so when you cache the credential you must first open a PowerShell session as your RBAC user to run the "Add-NcCredential" CmdLet and your main script must be run as the RBAC user that encrypted the credentials. Just a suggestion to avoid using user names and passwords in clear text within your code.

 

Hope that gives you a few tips towards getting it working. Let me know what the error message is

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.

mbeattie
112 Views

Hey Brendan,

 

Just as an example to improve the security of your script, rather than have user names and passwords within your code and then creating a credential object to connect to the cluster. EG:

 

Function Get_Device_Volumes($Device){
   $User            = "DOMAIN\SERVICEACCOUNT"
   $Password        = "SERVICEACCOUNT-PASSWORD"
   $SecurePass      = ConvertTo-SecureString -String $Password -AsPlainText -Force
   $Credential      = New-Object System.Management.Automation.PSCredential $User, $SecurePass
   $nacontroller    = Connect-NcController $Device -HTTPS -Credential $Credential
   $VolumeNameArray = Get-NcVol -Controller $nacontroller
   Return $VolumeNameArray
}

 

You can cache the Credential as the user who you will schedule the script to runas. EG:

 

$credential = Get-Credential
Add-NcCredential -Name 192.168.100.100 -Credential $credential

 

Then from within your script you can retrieve the cached credential and pass them as an input parameter into your function. EG:

 

Param(
   [Parameter(Mandatory = $True, HelpMessage="The Cluster name or IP Address")]
   [String]$Cluster,
   [Parameter(Mandatory = $True, HelpMessage="The Vserver Name")]
   [String]$Vserver,
   [Parameter(Mandatory = $False, HelpMessage = "The Credentials to authenticate to MySQL")]
   [System.Management.Automation.PSCredential]$Credential
)
#'------------------------------------------------------------------------------
Function GetVolumes{
   Param(
      [Parameter(Mandatory = $True, HelpMessage="The Cluster name or IP Address")]
      [String]$Cluster,
      [Parameter(Mandatory = $True, HelpMessage="The Vserver Name")]
      [String]$Vserver,
      [Parameter(Mandatory = $True, HelpMessage = "The Credentials to authenticate to MySQL")]
      [System.Management.Automation.PSCredential]$Credential
   )
   #'---------------------------------------------------------------------------
   #'Connect to the cluster if not already connected.
   #'---------------------------------------------------------------------------
   If((($global:CurrentNcController).Name -ne $Cluster)){
      Try{
         Connect-NcController -Name $Cluster -Credential $Credential -ErrorAction Stop | Out-Null
         Write-Host $("Connected to cluster ""$Cluster"" as user """ + $Credential.UserName)
      }Catch{
         Write-Warning -Message $("Failed connecting to cluster ""$Cluster"". Error " + $_.Exception.Message)
         Return $Null
      }
   }
   #'---------------------------------------------------------------------------
   #'Enumerate the volumes on the vserver.
   #'---------------------------------------------------------------------------
   Try{
      $volumes = Get-NcVol -Vserver $Vserver -ErrorAction Stop
      Write-Host "Enumerating Volumes on Vserver ""$Vserver"" on Cluster ""$Cluster"""
   }Catch{
      Write-Warning -Message $("Failed enumerating volumes on vserver ""$Vserver"" on cluster ""$Cluster"". Error " +  $_.Exception.Message)
      Return $Null
   }
   Return $volumes
}#'End Function GetVolumes.
#'------------------------------------------------------------------------------
#'Enumerate Cached Credential for the cluster if not provided.
#'------------------------------------------------------------------------------
If(-Not($Credential)){
   Write-Host "Enumerating cached credentials for Cluster ""$Cluster"""
   $Credential = (Get-NcCredential -Name $Cluster).Credential
}
If($Null -eq $Credential){
   Write-Warning -Message "Failed enumerating Credential for Cluster ""$Cluster"""
   Exit
}
#'------------------------------------------------------------------------------
#'Enumerate the vserver volumes. 
#'------------------------------------------------------------------------------
$volumes = GetVolumes -Cluster $Cluster -Vserver $Vserver -Credential $Credential
$volumes

 

Example Output:

 

PS C:\Scripts\> .\GetVolumes.ps1 -Cluster 192.168.100.100 -Vserver vserver1
Enumerating cached credentials for Cluster "192.168.100.100"
Enumerating Volumes on Vserver "vserver1" on Cluster "192.168.100.100"

Name                      State       TotalSize  Used  Available Dedupe Aggregate                 Vserver
----                      -----       ---------  ----  --------- ------ ---------                 -------
volume1                   online        10.0 GB           5.0 GB        aggr1                     vserver1
volume2                   online        10.0 GB           8.0 GB        aggr1                     vserver1
volume3                   online        10.0 GB           9.0 GB        aggr1                     vserver1
vserver1_root             online         1.0 GB         961.6 MB        aggr1                     vserver1

 

Hope that provides a useful example for you.

 

/Matt

If this post resolved your issue, help others by selecting ACCEPT AS SOLUTION or adding a KUDO.
Public