Mixed security style qtrees have always been a little bit
of a support nightmare, but when they’ve been implemented many moons ago when
someone thought they were a good idea, and you’ve now got millions of files on
the qtree, how do you get the required knowledge/insight to help you flip the
qtree security style?
We have a solution ;-)
Please see the following PowerShell script - copy and paste into a text editor and save as say
“ScanForSecurityStyleInfo.ps1” and run - simples (be patient, it may take a while, you can always check the
command-history logs on the node it’s pointed at to see where it’s at.)
WARNING: A tool
like this generates massive command-history logs on the node it’s pointed at, will
generate a lot of additional disk I/O and CPU processing cycles, so never run
this against a production system.
The Script
Note: Formatted for
blogger by replaced the tabs with <##>
##############################
##
ScanForSecurityStyleInfo ##
##############################
Param(
<##>[String]$Cluster,
<##>[String]$Username,
<##>[String]$Password,
<##>[String]$Vserver,
<##>[String]$Volume,
<##>[String]$Qtree
)
"";"+++++
ScanForSecurityStyleInfo (cDOT) +++++";""
"IMPORTANT:
If possible, run this against your DR system since it will generate substantial
..."
"IMPORTANT:
... disk, CPU, and logging (command-history.log) load on the destination system.";""
"NOTE:
This tool does not use protocol acccess ..."
"NOTE:
... it does not recquire NFS or CIFS access to the file system to be
scanned."
"NOTE:
You do not need to suspend mirrors if scanning DR.";""
"PERFORMANCE
TIP 1: Point this at the node-management LIF of the node that has the volume
you're scanning."
"PERFORMANCE
TIP 2: The server you're running this script on should ideally be local to the
cDOT system ..."
"PERFORMANCE
TIP 3: ... and of a reasonable spec (i.e. 4GB RAM minimum, 2 cores or better
recommended.)";""
#############################################
##
CHECK FOR DATA ONTAP POWERSHELL TOOLKIT ##
#############################################
If(!(Get-Module
DataONTAP)){Import-Module DataONTAP -ErrorAction SilentlyContinue}
If(!(Get-Module
DataONTAP)){"Cannot find Data ONTAP PowerShell Toolkit - exiting!";
""; EXIT}
#################################
##
1: ACQUIRE DETAILS FOR SCAN ##
#################################
"<<<<<
PART 1/3: ACQUIRE DETAILS FOR SCAN >>>>>";""
##
CLUSTER/USERNAME/PASSWORD/VSERVER ##
##
================================= ##
$SecurePass
= $null
If($Password){
$SecurePass = $Password | ConvertTo-SecureString -AsPlainText -Force }
">>>
Enter Connection Details ";""
If(!$Cluster) { $Cluster = Read-Host "Cluster " } else {
"Cluster = $Cluster"}
If(!$Username) { $Username
= Read-Host "Username" } else { "Username =
$Username" }
If(!$SecurePass)
{ $SecurePass = Read-Host "Password" -AsSecureString}; ("")
$Credential
= New-Object System.Management.Automation.PsCredential($Username,$SecurePass)
$Connection
= Connect-NcController -Name $Cluster -Credential $Credential -ErrorAction
SilentlyContinue
If(!$Connection){"Unable
to connect to $Cluster - exiting!"; ""; EXIT}
##
SVMs in CLUSTER ##
##
=============== ##
">>>
List of Data SVMs in $Cluster"; ""
$vsAttrs
= Get-NcVserver -Template
$vsQuery
= Get-NcVserver -Template
$vsQuery.VserverType
= "data"
[System.Array]$DataVservers
= (Get-NcVserver -Attributes $vsAttrs -Query $vsQuery).VserverName
If($DataVservers.count
-eq 0){ "There are no Data SVMs in $Cluster - exiting!";
""; EXIT}
$DataVservers
| Foreach { $_ }; ""
If(!$Vserver)
{ $Vserver = Read-Host "Select
Vserver " } else { "Vserver =
$Vserver" }
If(!($DataVservers
-Contains $Vserver)){"";"Vserver $Vserver does not exist -
exiting!";"";EXIT};""
$Global:CurrentNcController.Vserver
= $Vserver ## CONTEXT SET TO $VSERVER
##
ACQUIRE VOLUME TO BE SCANNED ##
##
============================ ##
">>>
List of Volumes in $Vserver "; ""
$Attrs
= Get-NcVol -Template
$Query
= Get-NcVol -Template
Initialize-NcObjectProperty
-object $Query -name VolumeStateAttributes
$Query.VolumeStateAttributes.IsVserverRoot
= ""
[System.Array]$VolumesList
= (Get-NcVol -Attributes $Attrs -Query $Query).Name
If($VolumesList.count
-eq 0){ "There are no data volumes in SVM $Vserver - exiting!";
""; EXIT}
$VolumesList
| Foreach { $_ }; ""
If(!$Volume){
$Volume = Read-Host "Select Volume" } else { "Volume to check =
$Volume" }
If(!($VolumesList
-Contains $Volume)){"";"Volume $Volume does not exist -
exiting!";"";EXIT};""
Initialize-NcObjectProperty
-object $Attrs -name VolumeIdAttributes
$Attrs.VolumeIdAttributes.JunctionPath
= ""
[String]$JunctionToVol
= (Get-NcVol -Name $Volume -Attributes $Attrs).VolumeIdAttributes.JunctionPath
$JunctionToVol
= $JunctionToVol.Substring(0,($JunctionToVol.Length - 1 - $Volume.Length)) #
Required for Read-NcDirectory
##
ACQUIRE MIXED QTREE TO BE SCANNED ##
##
================================= ##
">>>
List of Mixed Security Style Qtrees in $Vserver "; ""
$qQuery
= Get-ncQtree -Template
$qQuery.SecurityStyle
= "mixed"
$qQuery.Volume
= $Volume
[System.Array]$QtreesList
= (Get-NcQtree -Query $qQuery).Qtree ## -VserverContext $Vserver
If($QtreesList.Count
-eq 0){"No mixed qtrees in this volume - exiting!"; "";
EXIT}
$QtreesList
| Foreach { $_ }; ""
If(!$Qtree){
$Qtree = Read-Host "Select Qtree" } else { "Qtree to check =
$Qtree" }
If(!($QtreesList
-Contains $Qtree)){"";"This is not a mixed mode qtree -
exiting!";"";EXIT};""
$StartReadNcDirPath
= "/vol/$Volume/$Qtree"
"Read-NcDirectory
uses /vol/VOLNAME/QTREE = $StartReadNcDirPath"
#################
##
2: SCANNING ##
#################
"";"<<<<<
PART 2/3: SCANNING >>>>>";""
$StartDate
= date
">>>
START TIME = $StartDate";""
[System.Array]$Global:DiscoveredFiles =
"STYLE,UID,GID,BITS,CREATED,MODIFIED,ACCESSED,FILE @ FOLDER"
[System.Array]$Global:DiscoveredFolders
= "STYLE,UID,GID,BITS,CREATED,MODIFIED,ACCESSED,FOLDER"
[int64 ]$Global:FolderCount = 0
[int64 ]$Global:FileCount = 0
$Attributes = Read-NcDirectory -Template
$Attributes.Empty = ""
$Attributes.FileType = ""
$Attributes.Name = ""
$Attributes.AccessedTimestamp
= ""
$Attributes.ModifiedTimestamp
= ""
$Attributes.CreationTImestamp
= ""
##
Get-NcFileDirSecInfo FUNCTION ##
##
============================= ##
Function
Get-NcFileDirSecInfo {
<##>Param([String]$Path)
<##>$GetNcFileDirSec = Get-NcFileDirectorySecurity -Path
($JunctionToVol + $Path)
<##>[String]$EffectiveStyle = $GetNcFileDirSec.EffectiveStyle
<##>[String]$UnixUserId = $GetNcFileDirSec.UnixUserId
<##>[String]$UnixGroupId = $GetNcFileDirSec.UnixGroupId
<##>[String]$UnixModeBits = $GetNcFileDirSec.UnixModeBits
<##>[Stirng]$OutputString = ($EffectiveStyle + "," +
$UnixUserId + "," + $UnixGroupId + "," + $UnixModeBits +
",")
<##>RETURN
$OutputString
}
##
RECURSIVE SCANNING FUNCTION ##
##
=========================== ##
Function
GetDirInfoRecursive {
<##>Param([String]$PathToReadRecursive)
<##>Write-Host
"." -ForegroundColor Cyan -NoNewLine
<##>$GetDirInfo
= Read-NcDirectory $PathToReadRecursive -Attributes $Attributes
<##>Foreach
($line in $GetDirInfo){
<##><##>[String]$TimeInfo
= [String]$line.CreationTimestampDT + "," +
[String]$line.ModifiedTimestampDT + "," +
[String]$line.AccessedTimestampDT + ","
<##><##>If($line.FileType
-eq "directory"){
<##><##><##>If(($line.Name
-ne ".") -and ($line.Name -ne "..") -and ($line.Name -ne
".snapshot")) {
<##><##><##><##>$Global:FolderCount
++
<##><##><##><##>[String]$FileDirSecInfo
= Get-NcFileDirSecInfo ($PathToReadRecursive.SubString(4) + "/" +
$line.Name)
<##><##><##><##>$Global:DiscoveredFolders
+= ($FileDirSecInfo + $TimeInfo + $PathToReadRecursive + "/" +
$line.Name)
<##><##><##><##>If
($line.Empty -ne "False"){
<##><##><##><##><##>$NewPathToRead
= $PathToReadRecursive + "/" + $line.Name
<##><##><##><##><##>GetDirInfoRecursive
$NewPathToRead
<##><##><##><##>}
<##><##><##>}
<##><##>}
elseif($line.FileType -eq "file"){
<##><##><##>$Global:FileCount
++
<##><##><##>[String]$FileDirSecInfo
= Get-NcFileDirSecInfo ($PathToReadRecursive.SubString(4) + "/" +
$line.Name)
<##><##><##>If($FileDirSecInfo){
$Global:DiscoveredFiles += ($FileDirSecInfo + $TimeInfo + ($line.Name) + "
@ " + $PathToReadRecursive) }
<##><##>}
<##>}
}
GetDirInfoRecursive
$StartReadNcDirPath
$FinishDate
= date
"";"";">>>
FINISH TIME = $FinishDate";""
###############
##
3: OUTPUT ##
###############
"<<<<<
PART 3/3: OUTPUT >>>>>"
"";">>>
SEARCH STATISTICS:";""
"Processed
" + $Global:FileCount + " files and " + $Global:FolderCount +
" folders.";""
"Started
at $StartDate"
"Finished
at $FinishDate";""
##
OUTPUT TO TEXTFILE ##
##
================== ##
$Date
= Get-Date -uformat "%Y%m%d%H%M"
$OutputFileName
= "ScanResults_" + $Vserver + "_" + $Volume + "_"
+ $Qtree + "_" + $date
[System.Array]$StatsOut
= "","##### SEARCH STATISTICS
#####","",("Processed " + $Global:FileCount + "
files and " + $Global:FolderCount + "
folders."),"","Started at $StartDate","Finished
at $FinishDate",""
$Global:DiscoveredFiles | Out-File ($OutputFileName +
"_FILES.csv") -Encoding Default -Force
$Global:DiscoveredFolders
| Out-File ($OutputFileName + "_FOLDERS.csv") -Encoding Default
-Force
$StatsOut | Out-File ($OutputFileName +
"_STATS.txt") -Encoding Default -Force
"OUTPUT
FILES = $OutputFileName";""
Comments
Post a Comment