NetAppSecCheck.ps1
<#
.NOTES Information on running PowerShell scripts can be found here: -http://ss64.com/ps/syntax-run.html -https://technet.microsoft.com/en-us/library/bb613481.aspx This script requires PowerShell 7 or later to run, information on installing or upgrading PowerShell can be found here: -https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3 This script also requires that the ONTAP cluster is running 9.6 or later File Name: NetAppSecCheck.ps1 .SYNOPSIS Version: 1.1 - Added Summary, Full, and All output choices Cleaned up lots of formatting issues Reorganized Data Collection, Formatting, and Ouput sections 1.0 - Initial release .DESCRIPTION The intention of this script is to provide a quick check of several security configurations. Typically the following tools provide security related information for ONTAP clusters: -System Manager Dashboard -Unified Manager cluster security objectives -Active IQ Digital Advisor If a more thorough review is necessary of your environment, engage NetApp Services and request a Data Protection and Security Assessment The documents referenced in the KB article linked below should be consulted for the most up to date information -https://kb.netapp.com/onprem/ontap/os/How_to_perform_a_security_health_check_with_a_script_in_ONTAP .EXAMPLE .\NetAppSecCheck.ps1 All required values will be prompted for. #> <#PSScriptInfo .VERSION 1.1 .GUID 5a91e6dd-0287-4a5b-860b-eed6abf74b55 .AUTHOR Dan Tully .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI .PROJECTURI .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES .PRIVATEDATA #> #Requires -Version 7.0 #region Gather cluster address and credentials $NTAPCluster = Read-Host "Please enter the IP address or DNS name of the cluster to evaluate" $Credential = Get-Credential #endregion #region Test Connection/Authentication Try { $AuthCheck = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/cluster" -Credential $Credential -SkipCertificateCheck } Catch { if($_.ErrorDetails.Message) { Write-Host $_.ErrorDetails.Message } else { Write-Host $_ } Exit } #endregion #region Gather Data Write-Host Write-Host "Gathering Data...Please Wait..." Write-Host $Cluster = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/cluster" -Credential $Credential -SkipCertificateCheck $ONTAPGen = $Cluster.Version.generation $ONTAPMaj = $Cluster.Version.major $ONTAPMin = $Cluster.Version.minor $Version = $Cluster.Version.full $ChkVersion = $ONTAPMaj + $ONTAPMin / 10 $MgmtProtocols = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/protocol?fields=application,enabled" -Credential $Credential -SkipCertificateCheck $RSHMgmt = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/protocol?fields=application,enabled&application=rsh" -Credential $Credential -SkipCertificateCheck $TelnetMgmt = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/protocol?fields=application,enabled&application=telnet" -Credential $Credential -SkipCertificateCheck $LogForwarding = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/cluster/log" -Credential $Credential -SkipCertificateCheck $Certs = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/certificate?self_signed=true&type=server&fields=self_signed,common_name,vserver,type" -Credential $Credential -SkipCertificateCheck $OCSP = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/config/ocsp?fields=application,is_ocsp_enabled" -Credential $Credential -SkipCertificateCheck $FIPS = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/config?fields=is_fips_enabled" -Credential $Credential -SkipCertificateCheck $SystemTimeout = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/system/timeout" -Credential $Credential -SkipCertificateCheck $Banner = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login/banner" -Credential $Credential -SkipCertificateCheck $Motd = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login/motd" -Credential $Credential -SkipCertificateCheck $SecuritySsh = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/ssh?ciphers=*cbc*" -Credential $Credential -SkipCertificateCheck $NTPServers = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/cluster/time-service/ntp/server" -Credential $Credential -SkipCertificateCheck $ASUPConf = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/support/autosupport" -Credential $Credential -SkipCertificateCheck $Fpolicy = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/vserver/fpolicy?fields=status,engine" -Credential $Credential -SkipCertificateCheck $AdminUser = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/security/accounts?name=admin&fields=locked" -Credential $Credential -SkipCertificateCheck $DiagUser = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/security/accounts?name=diag&fields=locked" -Credential $Credential -SkipCertificateCheck $RSH = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login?application=rsh&fields=role,second_authentication_method,is_account_locked" -Credential $Credential -SkipCertificateCheck $Telnet = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login?application=telnet&fields=role,second_authentication_method,is_account_locked" -Credential $Credential -SkipCertificateCheck $Passwd = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login/role/config?fields=passwd-minlength,passwd-min-special-chars,passwd-min-digits,passwd-min-lowercase-chars,passwd-min-uppercase-chars,passwd-alphanum" -Credential $Credential -SkipCertificateCheck $Users = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login?fields=second-authentication-method,hash-function,is-account-locked,role" -Credential $Credential -SkipCertificateCheck $SSL = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/ssl?fields=client-enabled" -Credential $Credential -SkipCertificateCheck $HTTP = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login?application=http" -Credential $Credential -SkipCertificateCheck $ONTAPI = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login?application=ontapi" -Credential $Credential -SkipCertificateCheck $Samlsp = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/saml-sp/status?fields=status,is_enabled" -Credential $Credential -SkipCertificateCheck $CIFSSigning = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/vserver/cifs/security?is_signing_required=!null" -Credential $Credential -SkipCertificateCheck $LDAPBinding = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/vserver/cifs/security?session-security-for-ad-ldap=!null" -Credential $Credential -SkipCertificateCheck $Audit = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/vserver/audit?fields=vserver,state" -Credential $Credential -SkipCertificateCheck $NISData = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/svm/svms?nis.domain=!null" -Credential $Credential -SkipCertificateCheck $NullSS = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/volume?snapshot_policy=null&is_cluster_volume=true" -Credential $Credential -SkipCertificateCheck $NoneSS = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/volume?snapshot_policy=none&is_cluster_volume=true" -Credential $Credential -SkipCertificateCheck $AD = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/volume/snapshot/autodelete?enabled=true" -Credential $Credential -SkipCertificateCheck $KeyManager = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/security/key-managers" -Credential $Credential -SkipCertificateCheck $DriveProt = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/storage/aggregate?fields=drive-protection-enabled,node" -Credential $Credential -SkipCertificateCheck $VolEnc = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/volume?fields=encryption-type,is-encrypted" -Credential $Credential -SkipCertificateCheck $ClusterPeer = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/cluster/peer?fields=cluster,encryption_protocol_proposed,encryption_protocol" -Credential $Credential -SkipCertificateCheck If ($ChkVersion -ge 8) { $IPsec = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/security/ipsec?fields=*" -Credential $Credential -SkipCertificateCheck $IPsecPolicy = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/security/ipsec/policies" -Credential $Credential -SkipCertificateCheck } If ($ChkVersion -ge 10) { $ClusterAgent = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/cluster/agent/connection?fields=application-url" -Credential $Credential -SkipCertificateCheck $RestRoles = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/login/rest-role?api=/api/storage/volumes&fields=access" -Credential $Credential -SkipCertificateCheck $AR = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/svm/svms?fields=anti_ransomware_default_volume_state" -Credential $Credential -SkipCertificateCheck $VAR = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/volume?is-cluster-volume=true&fields=anti-ransomware-state" -Credential $Credential -SkipCertificateCheck } If ($ChkVersion -ge 11.1) { $MAV = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/security/multi-admin-verify" -Credential $Credential -SkipCertificateCheck } If ($ChkVersion -ge 12.1) { $SSLocking = Invoke-RestMethod -Method GET -Uri "https://$NTAPCluster/api/private/cli/volume?fields=snapshot_locking_enabled" -Credential $Credential -SkipCertificateCheck } #endregion #region Format Data $MgmtProtocolsOut = ForEach ($_ in $MgmtProtocols.records) { new-object psobject -Property @{ Application = ($_.application).ToString() Enabled = ($_.enabled).ToString() } } If ($LogForwarding.num_records -ne 0) { $LogData = ForEach ($_ in $LogForwarding.records) { new-object psobject -Property @{ Destination = ($_.Destination).ToString() Port = ($_.Port).ToString() } } } If ($Certs.num_records -ne 0) { $CertOut = ForEach ($_ in $Certs.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() CommonName = ($_.common_name).ToString() Serial = ($_.serial).ToString() CA = ($_.ca).ToString() Type = ($_.type).ToString() "Self-Signed" = ($_.self_signed).ToString() } } } $OCSPOut = ForEach ($_ in $OCSP.records) { new-object psobject -Property @{ Application = ($_.application).ToString() "OCSP Enabled" = ($_.is_ocsp_enabled).ToString() } } $FIPSOut = ForEach ($_ in $FIPS.records) { new-object psobject -Property @{ Interface = ($_.interface).ToString() "FIPS Enabled" = ($_.is_fips_enabled).ToString() } } $SecSSHData = @() If ($SecuritySsh.num_records -ne 0) { ForEach ($_ in $SecuritySsh.records) { $Vserver = $_.vserver $Ciphers = $_.ciphers -split "," ForEach ($_ in $Ciphers) { If ($_.contains("cbc")) { $SecSSHData += New-Object -TypeName psobject -Property @{VServer=$VServer; Cipher=$_} } } } } If ($NTPServers.num_records -ne 0) { $NTPOut = ForEach ($_ in $NTPServers.records) { new-object psobject -Property @{ "NTP Servers" = ($_.Server ).ToString() } } } $AsupOut = ForEach ($_ in $ASUPConf) { new-object psobject -Property @{ Transport = ($_.transport ).ToString() Enabled = ($_.enabled ).ToString() } } If ($Fpolicy.num_records -ne 0) { $FpolicyOut = ForEach ($_ in $Fpolicy.records) { new-object psobject -Property @{ VServer = ($_.vserver ).ToString() "Policy Name" = ($_.policy_name ).ToString() Status = ($_.status ).ToString() Engine = ($_.engine ).ToString() } } } $Locked = $AdminUser.records + $DiagUser.records $LockedOut = ForEach ($_ in $Locked) { new-object psobject -Property @{ Username = ($_.name ).ToString() Locked = ($_.locked ).ToString() } } If ($RSH.num_records -ne 0) { $RSHOut = ForEach ($_ in $RSH.records) { new-object psobject -Property @{ VServer = ($_.vserver ).ToString() Username = ($_.user_or_group_name ).ToString() Application = ($_.application ).ToString() AuthMethod = ($_.authentication_method ).ToString() "Role Name" = ($_.role ).ToString() Locked = ($_.is_account_locked ).ToString() "2ndAuthMethod" = ($_.second_authentication_method ).ToString() } } } If ($Telnet.num_records -ne 0) { $TelnetOut = ForEach ($_ in $Telnet.records) { new-object psobject -Property @{ VServer = ($_.vserver ).ToString() Username = ($_.user_or_group_name ).ToString() Application = ($_.application ).ToString() AuthMethod = ($_.authentication_method ).ToString() "Role Name" = ($_.role ).ToString() Locked = ($_.is_account_locked ).ToString() "2ndAuthMethod" = ($_.second_authentication_method ).ToString() } } } $PasswdOut = ForEach ($_ in $Passwd.records) { new-object psobject -Property @{ VServer = ($_.vserver ).ToString() Role = ($_.role ).ToString() Alphanumeric = ($_.passwd_alphanum ).ToString() "Min Len" = ($_.passwd_minlength ).ToString() "Min Spec Chars" = ($_.passwd_min_special_chars ).ToString() "Min Lowercase" = ($_.passwd_min_lowercase_chars ).ToString() "Min Uppercase" = ($_.passwd_min_uppercase_chars ).ToString() "Min Digits" = ($_.passwd_min_digits ).ToString() } } $UsersOut = ForEach ($_ in $Users.records) { new-object psobject -Property @{ VServer = ($_.vserver ).ToString() Username = ($_.user_or_group_name ).ToString() Application = ($_.application ).ToString() AuthMethod = ($_.authentication_method ).ToString() "Role Name" = ($_.role ).ToString() Locked = ($_.is_account_locked ).ToString() "2ndAuthMethod" = ($_.second_authentication_method ).ToString() "Hash Function" = ($_.hash_function ).ToString() } } $SSLOut = ForEach ($_ in $SSL.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() "Client Enabled" = ($_.client_enabled).ToString() } } $HTTPOut = ForEach ($_ in $HTTP.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Username = ($_.user_or_group_name).ToString() Application = ($_.application).ToString() AuthMethod = ($_.authentication_method).ToString() } } $ONTAPIOut = ForEach ($_ in $ONTAPI.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Username = ($_.user_or_group_name).ToString() Application = ($_.application).ToString() AuthMethod = ($_.authentication_method).ToString() } } If ($Samlsp.records.num_records -ne 0) { $SamlOut = ForEach ($_ in $Samlsp.records) { new-object psobject -Property @{ Node = ($_.node).ToString() Status = ($_.status).ToString() Enabled = ($_.is_enabled).ToString() } } } If ($CIFSSigning.num_records -ne 0) { $CIFSOut = ForEach ($_ in $CIFSSigning.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() "Signing Required" = ($_.is_signing_required).ToString() } } } If ($LDAPBinding.num_records -ne 0) { $LDAPOut = ForEach ($_ in $LDAPBinding.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() "Session Security for AD LDAP" = ($_.session_security_for_ad_ldap).ToString() } } } If ($Audit.num_records -ne 0) { $AuditOut = ForEach ($_ in $Audit.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Enabled = ($_.state).ToString() } } } If ($NISData.num_records -ne 0) { $NISSVMs = ForEach ($_ in $NISData.records) { new-object psobject -Property @{ VServer = ($_.name).ToString() NISDomain = ($_.nis.domain).ToString() } } } If ($NullSS.num_records -ne 0) { $NullSSData = ForEach ($_ in $NullSS.records) { new-object psobject -Property @{ Volume = ($_.volume).ToString() "Snapshot Policy" = "-" VServer = ($_.vserver).ToString() } } } If ($NoneSS.num_records -ne 0) { $NoneSSData = ForEach ($_ in $NoneSS.records) { new-object psobject -Property @{ Volume = ($_.volume).ToString() "Snapshot Policy" = ($_.snapshot_policy).ToString() VServer = ($_.vserver).ToString() } } } If ($AD.num_records -ne 0) { $ADData = ForEach ($_ in $AD.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Enabled = ($_.enabled).ToString() Volume = ($_.volume).ToString() } } } If ($DriveProt.num_records -ne 0) { $DriveProtData = ForEach ($_ in $DriveProt.records) { new-object psobject -Property @{ Aggregate = ($_.aggregate).ToString() Node = ($_.node).ToString() "Drive Protection Enabled" = ($_.drive_protection_enabled).ToString() } } } If ($VolEnc.num_records -ne 0) { $VolEncData = ForEach ($_ in $VolEnc.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Volume = ($_.volume).ToString() "Encryption Type" = ($_.encryption_type).ToString() "Is Encrypted" = ($_.is_encrypted).ToString() } } } If ($ClusterPeer.num_records -ne 0) { $ClusterPeerOut = ForEach ($_ in $ClusterPeer.records) { new-object psobject -Property @{ Cluster = ($_.cluster).ToString() "Encryption Protocol" = ($_.encryption_protocol).ToString() } } } If ($ChkVersion -ge 10) { $RestOut = ForEach ($_ in $RestRoles.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Role = ($_.role).ToString() API = ($_.api).ToString() Access = ($_.Access).ToString() } } If ($VAR.num_records -ne 0) { $VARData = ForEach ($_ in $VAR.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Volume = ($_.volume).ToString() "Anti Ransomware State" = ($_.anti_ransomware_state).ToString() } } } If ($AR.num_records -ne 0) { $ARData = ForEach ($_ in $AR.records) { new-object psobject -Property @{ VServer = ($_.name).ToString() "Anti Ransomware Default Volume State" = ($_.anti_ransomware_default_volume_state).ToString() } } } } If ($ChkVersion -ge 11.1) { $MAVOut = new-object psobject -Property @{ Enabled = ($MAV.enabled).ToString() "Required Approvers" = ($MAV.required_approvers).ToString() } } If ($ChkVersion -ge 12.1) { If ($SSLocking.num_records -ne 0) { $SSLockingOut = ForEach ($_ in $SSLocking.records) { new-object psobject -Property @{ VServer = ($_.vserver).ToString() Volume = ($_.volume).ToString() "Snapshot Locking Enabled" = ($_.snapshot_locking_enabled).ToString() } } } } #endregion function Header() { Write-Host Write-Host ("-"*120) Write-Host Write-Host "The intention of this script is to provide a quick check of several security configurations." Write-Host Write-Host (" "*8)"Typically the following tools provide security related information for ONTAP clusters:" Write-Host (" "*16)"System Manager Dashboard" Write-Host (" "*16)"Unified Manager cluster security objectives" Write-Host (" "*16)"Active IQ Digital Advisor" Write-Host Write-Host (" "*8)"If a more thorough review is necessary of your environment, please consider contacting" Write-Host (" "*8)"NetApp Services to request a Data Protection and Security Assessment" Write-Host Write-Host "The documents referenced in the KB article linked below should be consulted for the most up to date information" Write-Host Write-Host (" "*8)"https://kb.netapp.com/onprem/ontap/os/How_to_perform_a_security_health_check_with_a_script_in_ONTAP" Write-Host Write-Host ("-"*120) } function SummaryOutput() { $SummaryData = @() $SummaryData += New-Object -TypeName psobject -Property @{Topic="ONTAP Version"; Finding=$Version} $SummaryData += New-Object -TypeName psobject -Property @{Topic="RSH Disabled"; Finding=(!$RSHMgmt.records.enabled)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Telnet Disabled"; Finding=(!$TelnetMgmt.records.enabled)} If ($ChkVersion -ge 11.1) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Multi-Admin-Verify Configured"; Finding=$MAV.enabled} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Multi-Admin-Verify Configured"; Finding="Not available in this release"} } $SummaryData += New-Object -TypeName psobject -Property @{Topic="Syslog Forwarding Configured"; Finding=($LogForwarding.num_records -ne 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No Self-signed Certificates Present"; Finding=($Certs.num_records -eq 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="OCSP Enabled for all Applications"; Finding=(!$OCSPOut."OCSP Enabled".contains("False"))} $SummaryData += New-Object -TypeName psobject -Property @{Topic="FIPS Mode Enabled"; Finding=$FIPS.records.is_fips_enabled} $SummaryData += New-Object -TypeName psobject -Property @{Topic="CLI Timeout Enabled"; Finding=($SystemTimeout.timeout -gt 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Login Banner Configured"; Finding=($Banner.num_records -ne 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="MOTD Configured"; Finding=($MOTD.num_records -ne 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No CBC Ciphers Present"; Finding=($SecuritySsh.num_records -gt 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="3+ NTP Servers Configured"; Finding=($NTPServers.num_records -ge 3)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="AutoSupport Transport is HTTPS"; Finding=($ASUPConf.transport.contains("https"))} $SummaryData += New-Object -TypeName psobject -Property @{Topic="AutoSupport Enabled"; Finding=$ASUPConf.enabled} If ($ChkVersion -ge 10) { If ($ClusterAgent.num_records -ne 0) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Cloud Insights Configured"; Finding=($ClusterAgent.records.application_url.contains("cloudinsights.netapp.com"))} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Cloud Insights Configured"; Finding="False"} } } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Cloud Insights Configured"; Finding="Not available in this release"} } $SummaryData += New-Object -TypeName psobject -Property @{Topic="FPolicy Configured"; Finding=($Fpolicy.num_records -ne 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Admin User Locked"; Finding=$AdminUser.records.locked} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Diag User Locked"; Finding=$DiagUser.records.locked} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No Users Present with RSH Access"; Finding=($RSH.num_records -eq 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No Users Present with Telnet Access"; Finding=($Telnet.num_records -eq 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Password Complexity Configuration"; Finding="Please Consult Full Output for Details"} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Extended User Details"; Finding="Please Consult Full Output for Details"} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No SVMs with client-enabled SSL Access Present"; Finding=(!$SSLOut."Client Enabled".contains("True)"))} If ($ChkVersion -ge 10) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="API Access to /api/storage/volumes"; Finding="Please Consult Full Output for Details"} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="API Access to /api/storage/volumes"; Finding="Not available in this release"} } $SummaryData += New-Object -TypeName psobject -Property @{Topic="SAML Configured"; Finding=(!$SamlOut.enabled.contains("False"))} If ($CIFSSigning.num_records -ne 0) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="All CIFS SVMs have Signing Enabled"; Finding=(!$CifsOut."Signing Required".contains("False"))} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="All CIFS SVMs have Signing Enabled"; Finding="No CIFS SVMs Found"} } $SummaryData += New-Object -TypeName psobject -Property @{Topic="AD LDAP Session Security Enabled for all SVMs"; Finding=(!$LDAPOut."Session Security for AD LDAP".contains("none"))} $SummaryData += New-Object -TypeName psobject -Property @{Topic="NAS Auditing Configured"; Finding=($Audit.num_records -ne 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="NIS not Configured"; Finding=($NISData.num_records -eq 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No Volumes with Snapshot Policy of NULL"; Finding=($NullSS.num_records -eq 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No Volumes with Snapshot Policy of none"; Finding=($NoneSS.num_records -eq 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="No Volumes with Snapshot Autodeletion Enabled"; Finding=($AD.num_records -eq 0)} If ($ChkVersion -ge 10) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Anti-Ransomware Protection Enabled for all SVMs"; Finding=(!$ARData."Anti Ransomware Default Volume State".contains("disabled"))} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Anti-Ransomware Protection Enabled for all Volumes"; Finding=(!$VARData."Anti Ransomware State".contains("disabled"))} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Anti-Ransomware Protection Enabled for all SVMs"; Finding="Not available in this release"} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Anti-Ransomware Protection Enabled for all Volumes"; Finding="Not available in this release"} } If ($ChkVersion -ge 12.1) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Snapshot Locking Enabled for all Volumes"; Finding=(!$SSLockingOut."Snapshot Locking Enabled".contains("False"))} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Snapshot Locking Enabled for all Volumes"; Finding="Not available in this release"} } $SummaryData += New-Object -TypeName psobject -Property @{Topic="Key-Manager Configured"; Finding=($KeyManager.num_records -ne 0)} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Drive Encryption Enabled for all Aggregates"; Finding=(!$DriveProtData."Drive Protection Enabled".contains("False"))} $SummaryData += New-Object -TypeName psobject -Property @{Topic="Volume Encryption Enabled for all Volumes"; Finding=(!$VolEncData."Is Encrypted".contains("False"))} If ($ClusterPeer.num_records -ne 0) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Encryption Enabled for all Cluster Peers"; Finding=(!$ClusterPeerOut."Encryption Protocol".contains("none"))} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="Encryption Enabled for all Cluster Peers"; Finding="No Cluster Peers Found"} } If ($ChkVersion -ge 8) { $SummaryData += New-Object -TypeName psobject -Property @{Topic="IPsec Enabled"; Finding=$IPsec.enabled} $SummaryData += New-Object -TypeName psobject -Property @{Topic="IPsec Policies Configured"; Finding=($IPsecPolicy.num_records -ne 0)} } Else { $SummaryData += New-Object -TypeName psobject -Property @{Topic="IPsec Enabled"; Finding="Not available in this release"} $SummaryData += New-Object -TypeName psobject -Property @{Topic="IPsec Policies Configured"; Finding="Not available in this release"} } Write-Host Write-Host (" "*37)"General Overview of Security Configurations" Write-Host Write-Host ("-"*120) $SummaryData | Format-table Topic,Finding -HideTableHeaders | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) } function FullOutput() { Write-Host Write-Host (" "*39)"Full Details of Security Configurations" Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Running a recommended release of ONTAP" Write-Host "Reference: SU2" Write-Host Write-Host (" "*7)"ONTAP Version:" $Version Write-Host Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Telnet and Remote Shell (RSH) should be disabled" Write-Host "Reference: System Manager insights and TR-4569 section "Application methods"" $MgmtProtocolsOut | Format-Table Application,Enabled | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Multi-admin verification should be enabled" Write-Host "Reference: TR-4569 section "Multi-admin verification"" If ($ChkVersion -ge 11.1) { $MAVOut | Format-Table Enabled,"Required Approvers" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"Multi-admin-verify is not supported on this release. Consider upgrading to 9.11.1 or later." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Offloading of syslog information should be configured" Write-Host "Reference: TR-4569 section "Sending out syslog"" If ($LogForwarding.num_records -ne 0) { Write-Host (" "*7)"Cluster Log Destinations" $LogData | Format-Table Destination,Port | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: On production systems no self-signed ceritficates should exist" Write-Host (" "*15)"(the recommendation is met if no results are returned)" Write-Host "Reference: TR-4569 section "Creating a CA-signed digital certificate"" If ($Certs.num_records -ne 0) { $CertOut | Format-Table Vserver,CommonName,Serial,CA,Type,"Self-Signed" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: OCSP should be enabled" Write-Host "Reference: TR-4569 section "Online certificate status protocol"" $OCSPOut | Format-Table Application,"OCSP Enabled" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: FIPS Mode should be enabled" Write-Host "Reference: System Manager insights and TR-4569 section "Managing TLS and SSL"" $FIPSOut | Format-Table Interface,"FIPS Enabled" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: CLI timeout value should match your organization's requirements" Write-Host "Reference: TR-4569 section "CLI session timeout"" Write-Host Write-Host (" "*7)"CLI session timeout:" $SystemTimeout.timeout "minutes" Write-Host Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: The login banner and message of the day (motd) should match your organization's requirements" Write-Host "Reference: System Manager insights and TR-4569 section "Login banners" and "Message of the day"" Write-Host If ($Banner.num_records -ne 0){ Write-Host (" "*7)"Login banner configured - true" Write-Host } else{ Write-Host (" "*7)"Login banner configured - false" Write-Host } If ($Motd.num_records -ne 0){ Write-Host (" "*7)"MOTD configured - true" Write-Host } else{ Write-Host (" "*7)"MOTD configured - false" Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: No ciphers should exist that have names containing"cbc"" Write-Host (" "*15)"(the recommendation is met if no results are returned)" Write-Host "Reference: System Manager insights" If ($SecuritySsh.num_records -ne 0) { Write-Host Write-Host (" "*7)"Problematic Ciphers" $SecSSHData | Format-Table VServer,Cipher | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Problematic Ciphers Found." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: The number of servers configured for NTP should not be less than 3" Write-Host "Reference: System Manager insights and TR-4569 section "Network Time Protocol"" If ($NTPServers.num_records -ne 0) { $NTPOut | Format-Table "NTP Servers" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No NTP Servers Found." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: AutoSupport should use a secure protocol (HTTPS) and should be enabled" Write-Host "Reference: System Manager insights and TR-4569 section "NetApp AutoSupport"" $ASUPOut | Format-Table Transport,Enabled | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host If ($ChkVersion -ge 10) { Write-Host ("-"*120) Write-Host "Recommendation: Cloud Insights provides an external mode FPolicy server" Write-Host "Reference: TR-4572 section "Cloud Insights"" If ($ClusterAgent.num_records -ne 0) { $ClusterAgent.records | Format-Table | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host } Write-Host ("-"*120) Write-Host "Recommendation: FPolicy should be configured" Write-Host "Reference: System Manager insights" If ($Fpolicy.num_records -ne 0) { $FpolicyOut | Format-Table VServer,"Policy Name",Status,Engine | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Built in accounts should be locked" Write-Host "Reference: System Manager insights and TR-4569 section "Default administrative accounts"" $LockedOut | Format-table Username,Locked | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: No logins should exist with the telnet or rsh application" Write-Host (" "*15)"(the recommendation is met if no results are returned)" Write-Host "Reference: TR-4569 section "Application methods"" If ($RSH.num_records -ne 0) { $RSHOut | Format-table username,vserver,application,"role name",authmethod,"2ndAuthMethod",Locked | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No users found with RSH application access." Write-Host } If ($Telnet.num_records -ne 0) { $TelnetOut | Format-table username,vserver,application,"role name",authmethod,"2ndAuthMethod",Locked | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No users found with Telnet application access." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Configured password parameters should match your organization's policy" Write-Host "Reference: TR-4569 section "Password parameters"" $PasswdOut | Format-table vserver,role,Alphanumeric,"Min Len","Min Spec Chars","Min Lowercase","Min Uppercase","Min Digits" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: For each login the authentication-method should be public key for machine access and can be password for" Write-Host (" "*15)"user access" Write-Host (" "*15)"The second-authentication-method should not be none to enable MFA" Write-Host (" "*15)"The role should be the appropriate granting them the appropriate privilege to perform their job function" Write-Host (" "*15)"or required tasks" Write-Host (" "*15)"The hash-function should be sha512" Write-Host "Reference: TR-4569 section "SHA-512 support" and "Managing SSHv2" and "Roles, applications, and authentication" and " Write-Host (" "*10)"TR-4647 section "ONTAP SSH two-factor chained authentication"" $UsersOut | Format-table username,vserver,application,"role name",authmethod,"2ndAuthMethod",Locked,"Hash Function" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: For any SVM with client-enabled access, all related logins that are performing SDK or REST API calls " Write-Host (" "*15)"should use cert for Authentication Method field" Write-Host "Reference: TR-4569 section "Certificate-based API access"" Write-Host Write-Host (" "*7)"SSL Configuration" $SSLOut | Format-Table VServer,"Client Enabled" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } If ($HTTP.records.num_records -ne 0) { Write-Host (" "*7)"HTTP Users" $HTTPOut | Format-Table VServer,Username,Application,AuthMethod | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No HTTP Users Found." Write-Host } If ($ONTAPI.records.num_records -ne 0) { Write-Host (" "*7)"ONTAPI Users" $ONTAPIOut | Format-Table VServer,Username,Application,AuthMethod | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No ONTAPI Users Found." Write-Host } Write-Host ("-"*120) Write-Host If ($ChkVersion -ge 10) { Write-Host ("-"*120) Write-Host "Recommendation: You can prevent ONTAP administrators from using REST APIs for file access by setting access level " Write-Host (" "*15)"for /api/storage/volumes to none" Write-Host "Reference: TR-4569 section "Effect of REST APIs on NAS auditing"" $RestOut | Format-Table VServer,Role,API,Access | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } Write-Host ("-"*120) Write-Host } Write-Host ("-"*120) Write-Host "Recommendation: SAML should be configured" Write-Host "Reference: TR-4647 section "The requirement for strong administrative credentials"" If ($Samlsp.records.num_records -ne 0) { $SamlOut | Format-Table Node,Status,Enabled | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: For each SVM configured with CIFS the is-signing-required should be true" Write-Host "Reference: TR-4569 section "CIFS SMB signing and sealing"" If ($CIFSSigning.num_records -ne 0) { $CIFSOut | Format-Table VServer,"Signing Required" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: For each SVM configured with CIFS session-security-for-ad-ldap should be set to a minimum of sign " Write-Host (" "*15)"to match your organization's requirements" Write-Host "Reference: TR-4835 section "Microsoft LDAP channel binding requirement"" If ($LDAPBinding.num_records -ne 0) { $LDAPOut | Format-Table VServer,"Session Security for AD LDAP" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: NAS auditing should be enabled" Write-Host "Reference: TR-4569 section "NAS file system auditing"" If ($Audit.num_records -ne 0) { $AuditOut | Format-Table VServer,Enabled | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Auditing Configuration Found." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: NIS should not be configured (the recommendation is met if no results are returned)" Write-Host "Reference: TR-4569 section "Authentication methods"" If ($NISData.num_records -ne 0) { $NISSVMs | Format-Table vserver,nisdomain | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: All volumes should have Snapshot policies (the recommendation is met if no results are returned)" Write-Host "Reference: System Manager insights" If ($NullSS.num_records -ne 0) { $NullSSData | Format-Table volume,"Snapshot Policy",VServer | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Volumes with a Snapshot Policy of NULL." Write-Host } If ($NoneSS.num_records -ne 0) { $NoneSSData | Format-Table volume,"Snapshot Policy",VServer | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Volumes with a Snapshot Policy of None." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Snapshot auto-deletion should not be enabled for data volumes" Write-Host "Reference: System Manager insights" If ($AD.num_records -ne 0) { $ADData | Format-Table VServer,Volume,Enabled | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: SVMs should be configured for anti-ransomware" Write-Host "Reference: System Manager insights" If ($ChkVersion -ge 10) { If ($AR.num_records -ne 0) { $ARData | Format-Table VServer,"Anti Ransomware Default Volume State" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } } Else { Write-Host Write-Host (" "*7)"Anti-Ransomware Protection is not supported on this release. Consider upgrading to 9.10 or later." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Volume anti-ransomware-state should be enabled" Write-Host "Reference: System Manager insights" If ($ChkVersion -ge 10) { If ($VAR.num_records -ne 0) { $VARData | Format-Table VServer,Volume,"Anti Ransomware State" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } } Else { Write-Host Write-Host (" "*7)"Anti-Ransomware Protection is not supported on this release. Consider upgrading to 9.10 or later." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: snapshot-locking-enabled should be true for all volumes with snapshots" Write-Host "Reference: TR-4569 section "Snapshot copy locking"" If ($ChkVersion -ge 12.1) { If ($SSLocking.num_records -ne 0) { $SSLockingOut | Format-Table VServer,Volume,"Snapshot Locking Enabled" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } } Else { Write-Host Write-Host (" "*7)"Snapshot Copy Locking is not supported on this release. Consider upgrading to 9.12.1 or later." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: A key-manager should be configured and encryption should be enabled at either the disk, aggregate, " Write-Host (" "*15)"or volume layer " Write-Host "Reference: TR-4569 section "Storage encryption"" If ($KeyManager.num_records -ne 0) { Write-Host Write-Host (" "*7)"Key-manager is configured." } Else { Write-Host Write-Host (" "*7)"No Key-manager Found." } If ($DriveProt.num_records -ne 0) { $DriveProtData | Format-Table Aggregate,Node,"Drive Protection Enabled" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } If ($VolEnc.num_records -ne 0) { $VolEncData | Format-Table VServer,Volume,"Encryption Type","Is Encrypted" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Results Returned." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: Cluster peers should be configured with tls-psk for the encryption protocol" Write-Host "Reference: TR-4569 section "Data replication encryption"" If ($ClusterPeer.num_records -ne 0) { $ClusterPeerOut | Format-Table Cluster,"Encryption Protocol" | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host Write-Host (" "*7)"No Cluster Peer Relationships Found." Write-Host } Write-Host ("-"*120) Write-Host Write-Host ("-"*120) Write-Host "Recommendation: When required ipsec is configured and policies created" Write-Host "Reference: TR-4569 section "IPsec data-in-flight encryption"" If ($ChkVersion -ge 8) { Write-Host Write-Host (" "*7)"IPsec Enabled -" $IPsec.enabled Write-Host If ($IPsecPolicy.num_records -ne 0) { $IPsecPolicy.records | Format-Table | Out-String -Stream | ForEach-Object { ' ' * 8 + $_ } } Else { Write-Host (" "*7)"No IPsec Policies Found." Write-Host } } Else { Write-Host Write-Host (" "*7)"IPsec is not supported on this release. Consider upgrading to 9.8 or later." Write-Host } Write-Host ("-"*120) Write-Host } #region Begin logging $Now = get-date -f MM-dd-yyyy-HHmmss Start-Transcript -UseMinimalHeader -Path ".\$Now.txt" #endregion #region set up choices for output type $Title = "Would you like full or summary output?" $Prompt = "Enter your choice" $Choices = [System.Management.Automation.Host.ChoiceDescription[]] @("&Summary", "&Full", "&All") $Default = 0 $Choice = $host.UI.PromptForChoice($Title, $Prompt, $Choices, $Default) switch($Choice) { 0 { Header SummaryOutput } 1 { Header FullOutput } 2 { Header SummaryOutput FullOutput } } #endregion #stop logging Stop-Transcript |