# # # ---------------------------- # XSD SCHEMA DEFINATION # ---------------------------- # # # ----------------------------- # SCHEMATRON RULES DEFINITION # ----------------------------- # # # ----------------------------- # TRANSLATIONS DEFINITION # ----------------------------- # data _system_translations { ConvertFrom-StringData @' # check NFS service status # NFSServiceStatusCheck_Title=NFS service should be started NFSServiceStatusCheck_Problem=NFS service is not started. NFSServiceStatusCheck_Impact=Client computers will not be able to connect to the shares on the server using the NFS protocol. NFSServiceStatusCheck_Resolution=Start the NFS service. NFSServiceStatusCheck_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 1 (warning, security) - Check for anonymous access # NfsServiceUsingAnonymousLogon_Title=Anonymous access should be disabled. NfsServiceUsingAnonymousLogon_Problem=Anonymous access is enabled on a Network File System (NFS) share NfsServiceUsingAnonymousLogon_Impact=Anonymous users can access the share, which could be a security risk because the users could view files they shouldn't have permission to view. If write access is enabled, anonymous users could place viruses or other malicious software on the share. NfsServiceUsingAnonymousLogon_Resolution=Disable anonymous access and use an identity mapping solution such as Active Directory Domain Services (AD DS), Active Directory Lightweight Directory Services (AD LDS), User Name Mapping Service, or any RFC2307-based solution. NfsServiceUsingAnonymousLogon_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 2 (error, configuration) - check for domain functional level # NfsDomainFunctionalLevelSufficient_Title=The domain functional level should be Windows Server 2003 R2 or higher when using an identity mapping solution NfsDomainFunctionalLevelSufficient_Problem=The domain functional level is lower than Windows Server 2003 R2. NfsDomainFunctionalLevelSufficient_Impact=Users will not be properly authenticated. NfsDomainFunctionalLevelSufficient_Resolution=Use Active Directory Domains and Trusts to increase the domain functional level to Windows Server 2003 R2 or higher. NfsDomainFunctionalLevelSufficient_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 3 (error, configuration) - check for mapping solution when intersecting NFS and SMB shares # NfsSharingWithSMBWithoutMapping_Title=Folders that are shared by using both the SMB and NFS protocols should use mapped accounts NfsSharingWithSMBWithoutMapping_Problem=A folder that is shared by using both the Server Message Block (SMB) protocol and the Network File System (NFS) protocol has Anonymous logon or Unmapped Unix User Access (UUUA) enabled. NfsSharingWithSMBWithoutMapping_Impact=Users might not be able to access the same files by using the SMB protocol as they can by using the NFS protocol. NfsSharingWithSMBWithoutMapping_Resolution=Use the File and Storage Services page of Server Manager or Set-NfsMappingStore Windows Powershell cmdlet to configure Server for Network File System to use an appropriate identity mapping solution for mapping Windows accounts to non-Windows accounts. NfsSharingWithSMBWithoutMapping_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 5 (warning, configuration) - check for use of client groups # NfsClientGroupsDefinedOrInUse_Title=Server for NFS should be configured to use Netgroups NfsClientGroupsDefinedOrInUse_Problem=Server for Network File System (NFS) is configured to use ClientGroups instead of Netgroups. NfsClientGroupsDefinedOrInUse_Impact=Client-based fencing (access control) for clients is performed by using a deprecated, proprietary technology instead of an industry standard that provides centralized client-based fencing for Server for NFS. NfsClientGroupsDefinedOrInUse_Resolution=Use the appropriate centralized configuration, such as Active Directory Domain Services (AD DS) or Network Information Service (NIS), to enable Netgroups. NfsClientGroupsDefinedOrInUse_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 6 (warning, configuration) - check for legacy User Name Mapping Service with or without an RFC2307 based identity mapping solution # NfsUsingUnmpWithOrWithoutRfc2307_Title=Server for Network File System should use an RFC2307-based identity mapping solution NfsUsingUnmpWithOrWithoutRfc2307_Problem=Server for Network File System is configured to use the User Name Mapping Service. NfsUsingUnmpWithOrWithoutRfc2307_Impact=The compatibility of Server for Network File System is limited because it performs identity mapping by using a deprecated, proprietary technology instead of by using an identity mapping solution based on the RFC2307 industry standard. NfsUsingUnmpWithOrWithoutRfc2307_Resolution=Implement an RFC2307-based identity mapping solution such as Active Directory Domain Services (AD DS), Active Directory Lightweight Domain Services (AD LDS), or other compliant Lightweight Directory Access Protocol (LDAP) stores. NfsUsingUnmpWithOrWithoutRfc2307_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 8 (warning, configuration) - Check for Case sensitivity setting when also running SMB # NfsUsingCaseSensitiveWithSmbAndNfs_Title=Operating system case sensitivity should be disabled for file servers that support the NFS and SMB protocols NfsUsingCaseSensitiveWithSmbAndNfs_Problem=Case sensitivity is enabled in the operating system for a file server that supports the Network File System (NFS) and Server Message Block (SMB) protocols. NfsUsingCaseSensitiveWithSmbAndNfs_Impact=File names may appear and be accessed differently depending on whether the user is using the NFS or SMB protocol to access the files. Object names may also appear differently for some applications, potentially leading to compatibility problems. NfsUsingCaseSensitiveWithSmbAndNfs_Resolution=Use Registry Editor to disable case sensitivity in the operating system, or dedicate the server to hosting NFS resources. NfsUsingCaseSensitiveWithSmbAndNfs_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 9 (error, configuration) - Check necessary firewall ports open # NfsAllFirewallPortsOpen_Title=Windows Firewall should open all ports used by Server for Network File System NfsAllFirewallPortsOpen_Problem=Some ports used for Server for Network File System are closed in Windows Firewall. NfsAllFirewallPortsOpen_Impact=Users will not have predictable access to shares when using the Network File System (NFS) protocol. NfsAllFirewallPortsOpen_Resolution=Use Windows Firewall to open the appropriate ports. NfsAllFirewallPortsOpen_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. # NFS rule 10 (warning, configuration) - check that NFS server is being used. # NfsServerServiceInUse_Title=Server for Network File System should be used or uninstalled NfsServerServiceInUse_Problem=No Network File System (NFS) shares (exports) are configured for Server for Network File System. NfsServerServiceInUse_Impact=Users will not be able to access shared folders by using the NFS protocol. The unused service will consume system resources and increase the surface area for malicious users to attack without providing any functionality to users. NfsServerServiceInUse_Resolution=Use the File and Storage Services page of Server Manager or New-NfsShare Windows Powershell cmdlet to provision one or more NFS shares, or uninstall Server for Network File System if it is not being used. NfsServerServiceInUse_Compliant=The File and Storage Services Best Practices Analyzer scan has determined that you are in compliance with this best practice. '@ } Import-LocalizedData -BindingVariable _system_translations -filename NFS.psd1 $windir = $env:Windir . $windir\System32\BestPractices\v1.0\Models\Microsoft\Windows\FileServices\fscommon.ps1 # ------------------ # FUNCTIONS - NFS # ------------------ # function NfsCheckServiceStatus ([string]$serviceName="NfsService", [string]$computerName="localhost") { $nfsService = get-service -computername $computerName -name $serviceName if ($nfsService -eq $null) { $nfsServiceStatus = "NotInstalled" } else { switch ($nfsService.Status) { "Running" {$nfsServiceStatus = [string]$_} "Stopped" {$nfsServiceStatus = [string]$_} "Paused" {$nfsServiceStatus = [string]$_} "StartPending" {$nfsServiceStatus = [string]$_} "ContinuePending" {$nfsServiceStatus = [string]$_} "PausePending" {$nfsServiceStatus = [string]$_} "StopPending" {$nfsServiceStatus = [string]$_} default {throw 'Unknown or unrecognised service status'} } } $nfsServiceStatus } function NfsGetSmbShareList ([string]$computerName="localhost") { $smbShareList = @(get-WmiObject -ComputerName $computerName -namespace "root/CIMV2" Win32_Share | foreach-object -process {if ($_.Name[-1] -ne "$"){$_}}) $smbShareList } # Simple path prefix test. Does NOT account for SMB shares spanning mountpoints etc. # function NfsCheckNfsSharesForSmbShareOverlap ($nfsShareList=@(), $smbShareList=@()) { $overlapsFound = $false if (($nfsShareList.Count -gt 0) -and ($smbShareList.Count -gt 0)) { foreach ($nfsShare in $nfsShareList) { $nfsPath = [string]$nfsShare.Path foreach ($smbShare in $smbShareList) { if (($smbShare.Path.StartsWith($nfsPath, $true, $null)) -or ($nfsPath.StartsWith($smbShare.Path, $true, $null))) { $overlapsFound = $true return $overlapsFound } } } } $overlapsFound } function NfsGetNfsServerClientGroups ([string]$computerName="localhost") { $nfsClientGroups = @(get-WmiObject -ComputerName $computerName -namespace "root/Microsoft/Windows/NFS" MSFT_NfsClientGroup) $nfsClientGroups } function NfsGetNfsServerExportFencing ([string]$computerName="localhost") { $nfsExportFencing = @(get-WmiObject -ComputerName $computerName -namespace "root/Microsoft/Windows/NFS" MSFT_NfsSharePermission -filter "ClientType='clientgroup'") $nfsExportFencing } function NfsGetNfsShareList ([string]$computerName="localhost") { $nfsShareList = @(get-WmiObject -ComputerName $computerName -namespace "root/Microsoft/Windows/NFS" MSFT_NfsShare) $nfsShareList } function NfsGetUsernameMapping ([string]$computerName="localhost") { $nfsMappingConfig = get-WmiObject -ComputerName $computerName -namespace "root/Microsoft/Windows/NFS" MSFT_NfsMappingStore $nfsMappingConfig } function NfsCheckForMappingSolution ($nfsUsernameMappingConfiguration, $mappingTest) { switch ($mappingTest) { "MS-UNMP" {if ($nfsUsernameMappingConfiguration.UNMLookupEnabled) {$mappingSolution = $true } else {$mappingSolution = $false}} "RFC2307" {if (($nfsUsernameMappingConfiguration.ADLookupEnabled) -or ($nfsUsernameMappingConfiguration.LdapLookupEnabled)) {$mappingSolution = $true } else {$mappingSolution = $false}} "FLATFILE" {if ($nfsUsernameMappingConfiguration.PasswdFileLookupEnabled) {$mappingSolution = $true } else {$mappingSolution = $false}} default { $mappingSolution = $false} } $mappingSolution } function NfsCheckServerForClientGroupsDefinedOrUsed ($nfsClientGroups=$null, $nfsExportFencing=$null) { if (($nfsClientGroups -ne $null) -or ($nfsExportFencing -ne $null)) { $nfsClientGroupsDefinedOrUsed = $true } else { $nfsClientGroupsDefinedOrUsed = $false } $nfsClientGroupsDefinedOrUsed } function NfsCheckNfsSharesForAnonymousAccess ($nfsShareList) { $nfsAnonymousAccessEnabled = $false if ($nfsShareList.Count -gt 0) { foreach ($nfsShare in $nfsShareList) { if ($nfsShare.AnonymousAccess) { $nfsAnonymousAccessEnabled = $true break } } } $nfsAnonymousAccessEnabled } function NfsGetRpcBindData ([string]$computerName="localhost") { $rpcdata = rpcinfo $computerName $rpcdata } function NfsGetRpcBindServiceTitles ([string[]]$rpcdata=$(throw 'rpcdata array is required')) { $rpcTitles = @{} $rpcdata[1] | foreach { $e = @{} $e.program, $e.version, $e.netid, $e.address, $e.service, $e.owner = $_.split(" `t", [StringSplitOptions]::RemoveEmptyEntries) $rpcTitles += $e } $rpcTitles } function NfsGetRpcBindServiceRecords ([string[]]$rpcdata=$(throw 'rpcdata array is required')) { $patternIPv4='^0\.0\.0\.0\.(?[\d]+)\.(?[\d]+)' $patternIPv6='^::\.(?[\d]+)\.(?[\d]+)' $rpcRecords = @() $firewallObject = New-Object -com HNetCfg.FwMgr # Ignore the first three lines as not real data (just titles, underlines etc) # $rpcdata[3..$rpcdata.length] | foreach { $e = @{} [int]$e.program, [int]$e.version, $e.netid, $e.address, $e.service, $e.owner = $_.split(" `t", [StringSplitOptions]::RemoveEmptyEntries) switch -regex ($e.address) { $patternIPv4 {[int]$e.port = 256 * [int]$matches.portHigh + [int]$matches.portLow} $patternIPv6 {[int]$e.port = 256 * [int]$matches.portHigh + [int]$matches.portLow} default {throw 'unable to parse address record (in switch) - $e.address'} } $e.PortAllowed = NfsCheckFirewallPort $e.port $e.netid $firewallObject $rpcRecords += $e } $rpcRecords } function NfsCheckHostDomainJoined ([string]$computerName="localhost") { $nfsDomainJoined = $true { trap [ActiveDirectoryObjectNotFoundException] {$nfsDomainJoined = $false; continue} $nfsComputerDomain = [System.DirectoryServices.ActiveDirectory.Domain]::GetComputerDomain() } $nfsDomainJoined } function NfsCheckForDomainFunctionalLevel ([string]$computerName="localhost") { $nfsDomainFunctionalLevel = @{ DS_BEHAVIOR_WIN2000 = 0 DS_BEHAVIOR_WIN2003_WITH_MIXED_DOMAINS = 1 DS_BEHAVIOR_WIN2003 = 2 DS_BEHAVIOR_WIN2008 = 3 DS_BEHAVIOR_WIN2008R2 = 4 } $nfsRootDSE = [ADSI]"LDAP://rootDSE" if ($nfsRootDSE.domainFunctionality -ge $nfsDomainFunctionalLevel.DS_BEHAVIOR_WIN2003) { $nfsDomainFunctionalLevelIsSufficient = $true } else { $nfsDomainFunctionalLevelIsSufficient = $false } $nfsDomainFunctionalLevelIsSufficient } function NfsCheckForCaseSensitiveEnabled { $nfsKernelKey = Get-ItemProperty "hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\kernel" if ($nfsKernelKey.ObCaseInsensitive -eq $null) { $nfsCaseSensitive = $true } elseif ($nfsKernelKey.ObCaseInsensitive -eq 0) { $nfsCaseSensitive = $true } else { $nfsCaseSensitive = $false } $nfsCaseSensitive } $nfsIpVersion = @{ NET_FW_IP_VERSION_V4 = 0 NET_FW_IP_VERSION_V6 = 1 NET_FW_IP_VERSION_ANY = 2 } $nfsIpProtocol = @{ NET_FW_IP_PROTOCOL_UDP = 17 NET_FW_IP_PROTOCOL_TCP = 6 } function NfsCheckFirewallPort ([int]$port=$(throw 'non-zero port number required'), [string]$netid="tcp", $firewallObject=$null) { $ipVersion = 0 $ipProtocol = 0 $portAllowed = $null $portRestricted = $null if ($firewallObject -eq $null) { $firewallObject = New-Object -com HNetCfg.FwMgr } switch ($netid) { "udp" {$ipVersion = $nfsIpVersion.NET_FW_IP_VERSION_V4; $ipProtocol=$nfsIpProtocol.NET_FW_IP_PROTOCOL_UDP} "tcp" {$ipVersion = $nfsIpVersion.NET_FW_IP_VERSION_V4; $ipProtocol=$nfsIpProtocol.NET_FW_IP_PROTOCOL_TCP} "udp6" {$ipVersion = $nfsIpVersion.NET_FW_IP_VERSION_V6; $ipProtocol=$nfsIpProtocol.NET_FW_IP_PROTOCOL_UDP} "tcp6" {$ipVersion = $nfsIpVersion.NET_FW_IP_VERSION_V6; $ipProtocol=$nfsIpProtocol.NET_FW_IP_PROTOCOL_TCP} default {throw 'un-recognised value for netid'} } # Only set up for kernel owned ports (hence the "SYSTEM" application) # $firewallObject.IsPortAllowed("SYSTEM", $ipVersion, $port, $null, $ipProtocol, [ref]$portAllowed, [ref]$portRestricted) return $portAllowed } function NfsCheckServerForFirewallPortsOpen ($rpcRecords) { $allPortsOpen=$true foreach ($rpcRecord in $rpcRecords) { if ($rpcRecord.PortAllowed -ne $true) { $allPortsOpen = $false break } } $allPortsOpen } function GetNFSXml() { $nfsServerServiceStatus = NfsCheckServiceStatus "NfsService" if ($nfsServerServiceStatus -ne "Running") { $nfsServerServiceRunning = $false $nfsFormalizedServerServiceRunning = Formalize-BoolValue($nfsServerServiceRunning) @" $nfsFormalizedServerServiceRunning "@ } else { $nfsServerServiceRunning = $true $computerName = [System.Net.Dns]::GetHostName() $nfsDomainJoined = NfsCheckHostDomainJoined $computerName $nfsValidDomainFunctionalLevel = NfsCheckForDomainFunctionalLevel $computerName $nfsMappingConfiguration = NfsGetUsernameMapping $computerName $nfsClientGroupsDefined = NfsGetNfsServerClientGroups $computerName $nfsClientGroupsInUse = NfsGetNfsServerExportFencing $computerName $smbShareList = @(NfsGetSmbShareList $computerName) $nfsShareList = @(NfsGetNfsShareList $computerName) $nfsUsingMappingService = NfsCheckForMappingSolution $nfsMappingConfiguration "MS-UNMP" $nfsUsingRfc2307Service = NfsCheckForMappingSolution $nfsMappingConfiguration "RFC2307" $nfsUsingFlatFileMapping = NfsCheckForMappingSolution $nfsMappingConfiguration "FLATFILE" $nfsCaseSensitiveEnabled = NfsCheckForCaseSensitiveEnabled $nfsIsAnonymousAccessEnabled = NfsCheckNfsSharesForAnonymousAccess $nfsShareList $nfsIsSmbNfsShareOverlap = NfsCheckNfsSharesForSmbShareOverlap $nfsShareList $smbShareList $nfsClientgroupsDefinedOrInUse = NfsCheckServerForClientGroupsDefinedOrUsed $nfsClientGroupsDefined $nfsClientGroupsInUse $nfsRpcBindData = @(NfsGetRpcBindData $computerName) $nfsRpcBindRecords = @(NfsGetRpcBindServiceRecords $nfsRpcBindData) $nfsAllFirewallPortsOpen = NfsCheckServerForFirewallPortsOpen $nfsRpcBindRecords if (($smbShareList.Count -gt 0) -and ($nfsShareList.Count -gt 0) -and ($nfsUsingMappingService -eq $false) -and ($nfsUsingRfc2307Service -eq $false) -and ($nfsUsingFlatFileMapping -eq $false)) { $nfsSharedContentWithoutMapping = $true } else { $nfsSharedContentWithoutMapping = $false } if (($smbShareList.Count -gt 0) -and ($nfsShareList.Count -gt 0) -and ($nfsCaseSensitiveEnabled)) { $nfsCaseSentiveEnabledWhileUsingSmbAndNfs = $true } else { $nfsCaseSentiveEnabledWhileUsingSmbAndNfs = $false } if (($nfsServerServiceStatus -eq "Running") -and ($nfsShareList.Count -gt 0)) { $nfsServerServiceInUse = $true } else { $nfsServerServiceInUse = $false } $nfsFormalizedServerServiceRunning = Formalize-BoolValue($nfsServerServiceRunning) $nfsFormalizedServerServiceInUse = Formalize-BoolValue($nfsServerServiceInUse) $nfsFormalizedIsAnonymousAccessEnabled = Formalize-BoolValue($nfsIsAnonymousAccessEnabled) $nfsFormalizedValidDomainFunctionalLevel = Formalize-BoolValue($nfsValidDomainFunctionalLevel) $nfsFormalizedSharedContentWithoutMapping = Formalize-BoolValue($nfsSharedContentWithoutMapping) $nfsFormalizedClientgroupsDefinedOrInUse = Formalize-BoolValue($nfsClientgroupsDefinedOrInUse) $nfsFormalizedUsingMappingWithOrWithoutRfc2307 = Formalize-BoolValue($nfsUsingMappingService) $nfsFormalizedCaseSentiveEnabledWhileUsingSmbAndNfs = Formalize-BoolValue($nfsCaseSentiveEnabledWhileUsingSmbAndNfs) $nfsFormalizedAllFirewallPortsOpen = Formalize-BoolValue($nfsAllFirewallPortsOpen) @" $nfsFormalizedServerServiceRunning $nfsFormalizedServerServiceInUse $nfsFormalizedIsAnonymousAccessEnabled $nfsFormalizedValidDomainFunctionalLevel $nfsFormalizedSharedContentWithoutMapping $nfsFormalizedClientgroupsDefinedOrInUse $nfsFormalizedUsingMappingWithOrWithoutRfc2307 $nfsFormalizedCaseSentiveEnabledWhileUsingSmbAndNfs $nfsFormalizedAllFirewallPortsOpen "@ } } function FSmain($doc) { $nfsInstalled = Check-FeatureInstallStatus "FS-NFS-Service" if ($nfsInstalled -eq $true) { $nfsXml = GetNFSXml if ($nfsXml.Length -gt 0) { $doc.DocumentElement.CreateNavigator().AppendChild($nfsXml) } } } # # ------------------ # FUNCTIONS - END # ------------------ # # # ------------------------ # SCRIPT MAIN BODY - START # ------------------------ # # # Initialize to perform querying Role information # Setup # # Set the Target Namespace to be used by XML # $tns="http://schemas.microsoft.com/bestpractices/models/FileServices/NFS/2011/04" # # Create a new XmlDocument # $doc = Create-DocumentElement $tns "NFSComposite" $fsFeatureInstalled = Check-FeatureInstallStatus "File-Services" if($fsFeatureInstalled -eq $true) { FSmain($doc) } # # Role Information obtained. # TearDown $doc $doc.Save([Environment]::SystemDirectory + "\BestPractices\v1.0\Models\Microsoft\Windows\FileServices\tempNFS.xml")