data _system_translations { ConvertFrom-StringData @' # fallback text goes here (optional) NpsServiceStatus_Title=The Network Policy Server (NPS) service should be running. NpsServiceStatus_Problem=The Network Policy Server (NPS) service is not running. NpsServiceStatus_Impact=The Network Policy Server (NPS) service is unavailable. Client computers requesting access to the network cannot authenticate and are denied network access. NpsServiceStatus_Resolution=Start the Network Policy Server (NPS) service. NpsServiceStatus_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. AtleastOneCAConfigured_Title=The Health Registration Authority (HRA) server should be configured with at least one valid certification authority (CA). AtleastOneCAConfigured_Problem=The Health Registration Authority (HRA) server is not configured with a valid certification authority (CA). AtleastOneCAConfigured_Impact=The Health Registration Authority (HRA) server cannot acquire health certificates on behalf of Network Access Protection (NAP) clients. NAP client computers are denied network access. AtleastOneCAConfigured_Resolution=Configure the Health Registration Authority (HRA) server with at least one valid certification authority (CA). AtleastOneCAConfigured_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. HraAcceptsHttpHttps_Title=Internet Information Services (IIS) settings for the Health Registration Authority (HRA) server should accept HTTP and HTTPS communication. HraAcceptsHttpHttps_Problem_Warning=Internet Information Services (IIS) settings for the Health Registration Authority (HRA) server do not accept HTTP and HTTPS communication. HraAcceptsHttpHttps_Problem_Error=Internet Information Services (IIS) settings for the Health Registration Authority (HRA) server do not accept HTTP or HTTPS communication. HraAcceptsHttpHttps_Impact_Warning=Network Access Protection (NAP) client computers might not be able to acquire health certificates or communications with NAP client computers will not be encrypted with Secure Sockets Layer (SSL). HraAcceptsHttpHttps_Impact_Error=Network Access Protection (NAP) client computers cannot obtain health certificates. HraAcceptsHttpHttps_Resolution=To enable HTTPS communication, provision a Secure Sockets Layer (SSL) certificate on the Health Registration Authority (HRA) server, and then configure Internet Information Services (IIS) to accept HTTPS requests. To enable HTTP communication, configure IIS to accept HTTP requests. HraAcceptsHttpHttps_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. FirewallExemptionForHttpHttps_Title=Firewall settings for the Health Registration Authority (HRA) server should allow HTTP and HTTPS communication. FirewallExemptionForHttpHttps_Problem_Error=Firewall settings for the Health Registration Authority (HRA) server do not allow HTTP and HTTPS communications. FirewallExemptionForHttpHttps_Problem_Warning=Firewall settings for the Health Registration Authority (HRA) do not allow HTTP or HTTPS communication. FirewallExemptionForHttpHttps_Impact_Error=Incoming health certificate requests are blocked. Network Access Protection (NAP) client computers cannot obtain a health certificate from the Health Registration Authority (HRA) server. FirewallExemptionForHttpHttps_Impact_Warning=Incoming health certificate requests might be blocked. If certificate requests are blocked, Network Access Protection (NAP) client computers cannot obtain a health certificate from the Health Registration Authority (HRA) server. FirewallExemptionForHttpHttps_Resolution=Configure firewall exemption settings to allow HTTP and HTTPS communication for the Health Registration Authority (HRA) server. FirewallExemptionForHttpHttps_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. IISComponentsInstalled_Title=The Health Registration Authority (HRA) server should have all required Internet Information Services (IIS) components installed. IISComponentsInstalled_Problem=Required Internet Information Services (IIS) components are not installed on the Health Registration Authority (HRA) server. IISComponentsInstalled_Impact=The Health Registration Authority (HRA) server cannot process health certificate requests. Network Access Protection (NAP) client computers are denied network access. IISComponentsInstalled_Resolution=Reinstall the Health Registration Authority (HRA) role service and all dependent roles and role features. IISComponentsInstalled_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. NpsCrpEnabled_Title=Network Policy Server (NPS) should have at least one connection request policy enabled. NpsCrpEnabled_Problem=No connection request policies are enabled on Network Policy Server (NPS). NpsCrpEnabled_Impact=Client computers requesting access to the network cannot authenticate and are denied network access. NpsCrpEnabled_Resolution=Create and enable a connection request policy on Network Policy Server (NPS) to process client computer authentication requests. NpsCrpEnabled_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. NpsNetworkPolicyEnabled_Title=Network Policy Server (NPS) should have at least one network policy enabled. NpsNetworkPolicyEnabled_Problem=No network policies are enabled on Network Policy Server (NPS). NpsNetworkPolicyEnabled_Impact=Client computers requesting access to the network cannot be authorized and are denied network access. NpsNetworkPolicyEnabled_Resolution=Create and enable a network policy on Network Policy Server (NPS) to process client computer authorization requests. NpsNetworkPolicyEnabled_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. CertificateLifeTime_Title=The Health Registration Authority (HRA) server should be configured with a validity time for health certificates of at least 20 minutes and no more than 24 hours. CertificateLifeTime_Problem=The validity time configured for health certificates is less than 20 minutes or more than 24 hours. CertificateLifeTime_Impact=Network Access Protection (NAP) client computers will renew their health certificates too frequently or infrequently, and might be unable to acquire a health certificate. CertificateLifeTime_Resolution=Configure the validity time for health certificates to be greater than 20 minutes, but less than 24 hours. CertificateLifeTime_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. NpsAuthentication_Title=Network Policy Server (NPS) should be configured to use more secure authentication methods. NpsAuthentication_Problem=Network Policy Server (NPS) has the following policies configured that use less secure authentication methods.{0}{1} NpsAuthentication_Impact=Client computers requesting network access can use authentication methods that are less secure. NpsAuthentication_Resolution=Configure Network Policy Server (NPS) to use more secure authentication methods such as PEAP-MSCHAPv2 or PEAP-TLS. Identical authentication methods must also be configured on client computers. NpsAuthentication_Compliant=The NAP Best Practices Analyzer scan has determined that you are in compliance with this best practice. NasRunningLocally_Title=Network Policy Server (NPS) should be configured as a network access server (NAS), or NPS should be configured with RADIUS clients. NasRunningLocally_Problem=Network Policy Server (NPS) is not configured as a network access server (NAS) and RADIUS clients are not configured and enabled. NasRunningLocally_Impact=Network access requests cannot be evaluated by Network Policy Server (NPS). Client computers requesting access to the network cannot authenticate and are denied network access. NasRunningLocally_Resolution=Configure and enable RADIUS clients, or configure Network Policy Server (NPS) as a network access server (NAS). NasRunningLocally_Compliant=The NPAS Best Practices Analyzer scan has determined that you are in compliance with this best practice. PolicyType_CRP=Connection request policies: PolicyType_NP=Network policies: '@ } Import-LocalizedData -BindingVariable _system_translations -filename NPAS.psd1 # Function Description: # Append some general info (not specific to any role service) # # Arguments: # parent xml node, under which to add the general info nodes # # Return Value: # None # function GeneralInfo($element) { $now = Get-Date ; $nodeNow = $element.ownerDocument.CreateElement("ScanTime", $tns); $nodeTxt = $nodeNow.ownerDocument.CreateTextNode( $now.ToString("o") ); [void]$nodeNow.AppendChild( $nodeTxt ); $nodeNow.setAttribute("ticks", $now.Ticks); [void]$element.AppendChild($nodeNow); } # helper function to create document function Create-DocumentElement($ns, $name ) { [xml] "<$name xmlns='$ns'/>" } $tns="http://schemas.microsoft.com/mbca/models/NPAS/2009/11" # create a new XmlDocument $doc = Create-DocumentElement $tns "NPAS" # # Create a new XmlDocument # GeneralInfo $doc.DocumentElement ; $NPSNode = $doc.CreateElement("NPSSERVER",$tns) [void]$doc.DocumentElement.AppendChild($NPSNode) $HRANode = $doc.CreateElement("HRASERVER",$tns) [void]$doc.DocumentElement.AppendChild($HRANode) #$NodeNPASComposite = setXmlElement $doc $doc.DocumentElement $tns "NPASComposite" # # Function Description: # # This function will add the Server Manager module so that Roles # can be queried # # Arguments: # # None # # Return Value: # # None # function RoleQueryInitialize { Import-Module ServerManager } # # Function Description: # # This function will remove the Server Manager module after the Roles # have been queried # # Arguments: # # None # # Return Value: # # None # function RoleQueryShutdown { Remove-Module ServerManager } # # Function Description: # # This function will check to see if the specified role is installed # # Arguments: # # $roleId - Id of the Role # # Return Value: # # $true - If Role is Installed # $false - If Role is not Installed # function IsRoleInstalled ( $roleId ) { $roleInstalled = $false # Use the Server Manager CmdLet to obtain detail about Role $Role = Get-WindowsFeature $roleId if ( $Role -ne $null ) { $roleInstalled = $Role.Installed } # Return the result return $roleInstalled } # Function Description: # Checks if the specified Service is Running # # Arguments: # $serviceName: Service Name # # Return Value: # Boolean. true if the service is running, false otherwise function IsServiceRunning($serviceName) { if (-not ([appdomain]::CurrentDomain.getassemblies() |? {$_.ManifestModule -like “system.serviceprocess”})) {[void][System.Reflection.Assembly]::LoadWithPartialName(’system.serviceprocess’)} $result = $false $machineName = "localhost" $serviceResults = [System.ServiceProcess.ServiceController]::GetServices($machineName) | where{ (($_.name -eq $serviceName) -or ($_.displayname -eq $serviceName))} if ($serviceResults -eq $null) { $result = $false } else { $serviceStatus = get-service $serviceResults.name $result = $serviceStatus.status -eq "Running" } # Return the result of the rule return $result } # # Function Description: # # This function will create and return a COM Object # # Arguments: # # $ProgId - Specifies type of COM object to create # # Return Value: # # $comObj - Newly created COM object # $null - if failure # function CreateComObject ( $ProgId ) { $comObj = New-Object -com $ProgId return $comObj } # Function Description: # This function will obtain the Config String for the CA identified by $flags # # Arguments: # $flags - Flags which identify the CA # # Return Value: # $configString - Config String for the specified CA # $null - if failure # function GetCAConfigString ( $flags ) { $certConfig = CreateComObject "CertificateAuthority.Config.1" if ($certConfig -eq $null) { return $null } $configString = $certConfig.GetConfig( $flags ) return $configString } # Function Description: # This function will obtain Type of specified CA # # Arguments: # $certAdmin - CertificateAuthority Admin object # $configString - Config String which identifies the CA # # Return Value: # $caType - Type of the specified CA # $null - if failure # function GetCAType ( $certAdmin, $configString ) { if ( !$certAdmin -or !$configString ) { return $null } $caType = $certAdmin.GetCAProperty( $configString, 10, 0, 1, 2 ) # Return the result return $caType } # Function Description: # This function will check if CA is Enterprise CA # # Arguments: # $caTypeEnum - Type of CA to check against # $caType - Type of CA # # Return Value: # $true - if CA is of specified type # $false - otherwise # function CheckCAType( $caTypeEnum, $caType ) { $compare = $false switch ( $catypeEnum ) { "Enterprise" { # Compare with ENTERPRISE_ROOTCA(0) or ENUM_ENTERPRISE_SUBCA(1) if ( ( $caType -eq 0 ) -or ( $caType -eq 1 ) ) { $compare = $true } } "StandAlone" { # Compare with ENUM_STANDALONE_ROOTCA(3) if ( $caType -eq 3 ) { $compare = $true } } } # Return the result return $compare } # Function Description: # Checks if # 1. the CA is installed # 2. CA is running # 3. CA is StandAlone CA # # Arguments: # $ADCSCertAuthorityInstalled - boolean value which indicates if CA is installed # # Return Value: # $IsStandAloneCA- true if StandAlone CA is installed and running, false otherwise # function IsStandAloneCARunning($ADCSCertAuthorityInstalled) { $result = $false if ($ADCSCertAuthorityInstalled -eq $true) { # Pre-Check whether the service is running $ADCSRunning = IsServiceRunning "certsvc" if ($ADCSRunning -eq $true) { # Create the Certificate Admin Object $certAdmin = CreateComObject "CertificateAuthority.Admin.1" # Obtain the config string for the CA using CC_LOCALCONFIG (0x3) $certConfigFlags = 0x3 $configString = GetCAConfigString $certConfigFlags # Obtain the type of CA $caType = GetCAType $certAdmin $configString # Check to see if this is a StandAlone CA $result = CheckCAType "StandAlone" $caType } } # Return the result return $result } # Function Description: # Checks if NPS service is Running # # Arguments: # None # # Return Value: # Boolean. true if NPS service is running, false otherwise function IsNpsServiceStatus { $result = $false $result = IsServiceRunning "ias" # Return the result of the rule return $result } # Function Description: # Checks if atleast one Connection Request Policy is enabled # # Arguments: # $xdNpsSvrCfg: NPS configuration # # Return Value: # Boolean. true if atleast one Connection Request Policy is enabled, # false otherwise # function IsNpsCrpEnabled($xdNpsSvrCfg) { $result = $false $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $proxyPoliciesNode = $temp.Children.Proxy_Policies.Children # If CRP node exists if($proxyPoliciesNode) { # For each CRP, find if any is enabled $proxyPoliciesEnumerator = $proxyPoliciesNode.GetEnumerator() foreach($_ in $proxyPoliciesEnumerator) { if($_.Properties.Policy_Enabled) { $proxyEnabled = $_.Properties.Policy_Enabled.'#text' } else { # If Proxy_Enabled Tag does not exist then the default policy is enabled. $proxyEnabled = '1' } if($proxyEnabled -eq '1') { $result = $true break } } } #endof if($proxyPoliciesNode) # Return the result of the rule return $result } # Function Description: # Checks if Radius Server Group exists corresponding to the Proxy profile # # Arguments: # $xdNpsSvrCfg: NPS configuration # $proxyProfilesName: Name of the Proxy Profile # # Return Value: # Boolean. true if Radius Server Group exists for the corresponding # Proxy Profile, false otherwise # function DoesRadiusServerGroupExists($xdNpsSvrCfg, $proxyProfilesName) { $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $radiusServerGroupsNode = $temp.Children.RADIUS_Server_Groups.Children if($radiusServerGroupsNode) { $radiusServerGroupsEnumerator = $radiusServerGroupsNode.GetEnumerator() foreach($_ in $radiusServerGroupsEnumerator) { # ensure that the name configured in proxy profile exists in # Radius Server Group if($_.name -eq $proxyProfilesName) { # We have identified that the server acts as a proxy $result = $true break } } } $result } # Function Description: # Checks if NPS proxy is enabled for the given Proxy Policy # # Arguments: # $xdNpsSvrCfg: NPS configuration # $proxyPoliciesName: Name of the Proxy Policy # # Return Value: # Boolean. true if Nps is configured as a Proxy for the given Proxy profile, # false otherwise # function DoesProxyProfileExists($xdNpsSvrCfg, $proxyPoliciesName) { $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $proxyProfilesNode = $temp.Children.Proxy_Profiles.Children # obtain the corresponding msAuthProviderName if($proxyProfilesNode) { $proxyProfilesEnumerator = $proxyProfilesNode.GetEnumerator() foreach($_ in $proxyProfilesEnumerator) { if($_.name -eq $proxyPoliciesName) { $proxyProfilesName = $_.Properties.msAuthProviderName.'#text' $result = DoesRadiusServerGroupExists $xdNpsSvrCfg $proxyProfilesName } if($result -eq $true) { # We have identified that the server acts as a proxy break } } # endof foreach($_ in $proxyProfilesEnumerator) } $result } # Function Description: # Checks if Nps Server is configured as a Proxy # # Arguments: # $xdNpsSvrCfg: NPS configuration # # Return Value: # Boolean. true if Nps Server is configured as a Proxy, # false otherwise # function IsNpsProxyConfigured($xdNpsSvrCfg) { # For NPS to be configured as a proxy, we need to check Proxy_Policies node # For each enabled Proxy_Policies, we need to identify the Profile which has a # valid Radius Server configured $result = $false $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $proxyPoliciesNode = $temp.Children.Proxy_Policies.Children if($proxyPoliciesNode) { $proxyPoliciesEnumerator = $proxyPoliciesNode.GetEnumerator() foreach($_ in $proxyPoliciesEnumerator) { # check if proxy policy is enabled $proxyPoliciesName = $_.name $proxyEnabled = $_.Properties.Policy_Enabled.'#text' # Only for the proxy policy which are enabled, iterate through all # the profiles if($proxyEnabled -eq '1') { $result = DoesProxyProfileExists $xdNpsSvrCfg $proxyPoliciesName } if($result -eq $true) { # We have identified that the server acts as a proxy break } } #endof foreach($_ in $proxyPoliciesEnumerator) } #endof if($proxyPoliciesNode) # Return the result return $result } # Function Description: # Checks if atleast one Network Policy is enabled # # Arguments: # $xdNpsSvrCfg: NPS configuration # # Return Value: # Boolean. true if atleast one Network Policy is enabled, # false otherwise # function IsNpsNetworkPolicyEnabled($xdNpsSvrCfg) { #If NPS is configured as a proxy, then we need not have Network Policy enabled $result = $false #Find if NPS is configured as a proxy $boolNpsProxyConfigured = IsNpsProxyConfigured($xdNpsSvrCfg) $networkPolicyEnabledCount = 0 $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $networkPolicyNode = $temp.Children.NetworkPolicy.Children # If Network Policy Node exists if($networkPolicyNode) { # For each Network Policy, find if any is enabled $networkPolicyEnumerator = $networkPolicyNode.GetEnumerator() foreach($_ in $networkPolicyEnumerator) { if($_.Properties.Policy_Enabled) { $networkPolicyEnabled = $_.Properties.Policy_Enabled.'#text' } else { # If Policy_Enabled Tag does not exist then the default policy is enabled. $networkPolicyEnabled = '1' } if($networkPolicyEnabled -eq '1') { $networkPolicyEnabledCount += 1 } } } #endof if($NetworkPolicyNode) # Atleast one Network Policy should be enabled or NPS should be a proxy $result = (($networkPolicyEnabledCount -ge 1) -or ($boolNpsProxyConfigured -eq $true)) # Return the result of the rule return $result } # Function Description: # Verifies authentication method # # Arguments: # $ProfileNode: Either CRP or NP node # # Return Value: # result - Array of CRPs/NPs names which are configured with less secure # authentication methods # count - This is pass by reference and indicates the number of CRPs/NPs # that are configured with less secure authentication methods. # caller doesn't have to initialize the value of count function CheckAuthenticationMethod($profileNode, [REF]$count) { # Authentication Methods Attribute in ias.xml and its value # Pap, Spap msNPAuthenticationType2 = 1 # Chap msNPAuthenticationType2 = 2 # msChap msNPAuthenticationType2 = 3 # msChapv2 msNPAuthenticationType2 = 4 # WithoutAuth msNPAuthenticationType2 = 7 # Peap msNPAuthenticationType2 = 5, # msNPAllowedEapType = "19" followed by 30 zero # EAP-MSChap v2 msNPAuthenticationType2 = 5, # msNPAllowedEapType = "1a" followed by 30 zero $AuthType = @{} $AuthType.PAP = 1 $AuthType.CHAP = 2 $AuthType.MSCHAP = 3 $AuthType.MSCHAPV2 = 4 $AuthType.EAP = 5 $AuthType.WithoutAuth = 7 $isSupportedEapType = $TRUE; $isSavedMachineHealthCheckOnly = $FALSE; $result = @() $count.Value = 0 # check if node exists if($profileNode) { # Enumerate each profile $profileEnumerator = $profileNode.GetEnumerator() foreach($_ in $profileEnumerator) { # for every Radius Profile, initialize the values $isSupportedEapType = $TRUE; $isSavedMachineHealthCheckOnly = $FALSE; # Ensure supported EAP methods are configured $msNPAllowedEapTypeNode = $_.Properties.msNPAllowedEapType foreach($msNPAllowedEapType in $msNPAllowedEapTypeNode) { if($msNPAllowedEapType.'#text' -eq '04000000000000000000000000000000' -or $msNPAllowedEapType.'#text' -eq '1a000000000000000000000000000000' ) { $isSupportedEapType = $FALSE; } } # Ensure "Perform machine health check only" is not enabled $msSavedMachineNode = $_.Properties.msSavedMachineHealthCheckOnly foreach($msSavedMachineType in $msSavedMachineNode) { if($msSavedMachineType.'#text' -eq '1') { $isSavedMachineHealthCheckOnly = $TRUE; } } # Ensure supported Authentication methods are configured $msNPAuthenticationTypeNode = $_.Properties.msNPAuthenticationType2 foreach($msNPAuthenticationType in $msNPAuthenticationTypeNode) { if($msNPAuthenticationType.'#text' -eq $AuthType.PAP -or $msNPAuthenticationType.'#text' -eq $AuthType.CHAP -or $msNPAuthenticationType.'#text' -eq $AuthType.MSCHAP -or $msNPAuthenticationType.'#text' -eq $AuthType.MSCHAPV2 -or ($msNPAuthenticationType.'#text' -eq $AuthType.WithoutAuth -and $isSavedMachineHealthCheckOnly -eq $FALSE) -or ($msNPAuthenticationType.'#text' -eq $AuthType.EAP -and $isSupportedEapType -eq $FALSE) ) { $temp = " " + $_.name $result = $result + $temp $count.Value += 1 break } } } # endof foreach($_ in $radiusProfileEnumerator) } # endof if($radiusProfileNode) # Return the result of the rule return $result } # Function Description: # Verifies Supported authentication method are configured for CRP and NP # # Arguments: # $xdNpsSvrCfg: NPS configuration # # Return Value: # returns an xml blob # # function CheckNpsAuthenticationMethod($xdNpsSvrCfg) { $isSupportedAuthForNP = $false $isSupportedAuthForCRP = $false # We need to check CRP and NP for Authentication methods $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $radiusProfileNode = $temp.Children.RadiusProfiles.Children $proxyProfileNode = $temp.Children.Proxy_Profiles.Children $authResult = @{} $npCount = 0 $crpCount = 0 $authResult.np = CheckAuthenticationMethod $radiusProfileNode ([REF]$npCount) $authResult.crp = CheckAuthenticationMethod $proxyProfileNode ([REF]$crpCount) if($crpCount -gt 0) { $crpList = $authResult.crp -join "`n" $crpList = $crpList -replace '{',' ' $crpList = $crpList -replace '}',' ' $crpList = "`n`n " + $_system_translations.PolicyType_CRP + "`n" + $crpList } if($npCount -gt 0) { $npList = $authResult.np -join "`n" $npList = $npList -replace '{',' ' $npList = $npList -replace '}',' ' $npList = "`n`n " + $_system_translations.PolicyType_NP + "`n" + $npList } if (! ($npCount -eq 0 -and $crpCount -eq 0)) { $result = @" false $crpList $npList "@ } else { $result = @" true "@ } # Return the result of the rule return $result } # Function Description: # Verifies if there is any NAS services running locally # # Arguments: # $xdNpsSvrCfg: NPS configuration # # Return Value: # Boolean. true if atleast one NAS is running locally, # false otherwise # function IsNasRunningLocally($xdNpsSvrCfg) { $result = $false $radiusClientEnabled = '0' #check if any Radius client is configured $temp1 = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $temp2 = $temp1.Children.Protocols.Children.Microsoft_Radius_Protocol $radiusClientsNode = $temp2.Children.Clients.Children if($radiusClientsNode) { $radiusClientsEnumerator = $radiusClientsNode.GetEnumerator() foreach($_ in $radiusClientsEnumerator) { $radiusClientEnabled = $_.Properties.Radius_Client_Enabled.'#text' } } # Initialize to perform querying Role information RoleQueryInitialize # RRAS installed $rrasInstalled = (IsRoleInstalled “NPAS”) -and (IsRoleInstalled “NPAS-RRAS-Services”) -and (IsRoleInstalled “NPAS-RRAS”) # DHCP installed $dhcpInstalled = IsRoleInstalled “DHCP” # TSG installed $tsgInstalled = IsRoleInstalled "RDS-Gateway" # HRA installed $hraInstalled = (IsRoleInstalled “NPAS”) -and (IsRoleInstalled “NPAS-Health”) # HCAP installed $hcapInstalled = (IsRoleInstalled “NPAS”) -and (IsRoleInstalled “NPAS-Host-Cred”) # Role Information obtained. RoleQueryShutdown # RRAS service Running $rrasRunning = $false $rrasRunning = IsServiceRunning "RemoteAccess" # DHCP service Running $dhcpRunning = $false $dhcpRunning = IsServiceRunning "DHCPServer" # TSG service Running $tsgRunning = $false $tsgRunning = IsServiceRunning "TSGateway" $allNasSourceTagCRP = $false $tsgSourceTagCRP = $false $rrasSourceTagCRP = $false $dhcpSourceTagCRP = $false $hraSourceTagCRP = $false $hcapSourceTagCRP = $false $allNasSourceTagNP = $false $tsgSourceTagNP = $false $rrasSourceTagNP = $false $dhcpSourceTagNP = $false $hraSourceTagNP = $false $hcapSourceTagNP = $false # Get Policy_SourceTag of CRP $temp = $xdNpsSvrCfg.Root.Children.Microsoft_Internet_Authentication_Service $proxyPolicyNode = $temp.Children.Proxy_Policies.Children # Get Policy_SourceTag of NP $networkPolicyNode = $temp.Children.NetworkPolicy.Children # If Proxy Policy Node exists if($proxyPolicyNode) { # For each CRP, find the sourceTag $proxyPolicyEnumerator = $proxyPolicyNode.GetEnumerator() foreach($_ in $proxyPolicyEnumerator) { $proxyPolicyEnabled = $_.Properties.Policy_Enabled.'#text' if($proxyPolicyEnabled -eq '1') { switch($_.Properties.Policy_SourceTag.'#text') { "0" { $allNasSourceTagCRP = $true } "1" { $tsgSourceTagCRP = $true } "2" { $rrasSourceTagCRP = $true } "3" { $dhcpSourceTagCRP = $true } "5" { $hraSourceTagCRP = $true } "6" { $hcapSourceTagCRP = $true } } } } } #endof if($ProxyPolicyNode) # If Network Policy Node exists if($networkPolicyNode) { # For each Network Policy, find the sourceTag $networkPolicyEnumerator = $networkPolicyNode.GetEnumerator() foreach($_ in $networkPolicyEnumerator) { $networkPolicyEnabled = $_.Properties.Policy_Enabled.'#text' if($networkPolicyEnabled -eq '1') { switch($_.Properties.Policy_SourceTag.'#text') { "0" { $allNasSourceTagNP = $true } "1" { $tsgSourceTagNP = $true } "2" { $rrasSourceTagNP = $true } "3" { $dhcpSourceTagNP = $true } "5" { $hraSourceTagNP = $true } "6" { $hcapSourceTagNP = $true } } } } } #endof if($networkPolicyNode) # Check if IIS is installed $iisInstalled = IsIISComponentsInstalled # Check if IIS is running $iisRunning = $false $iisRunning = IsServiceRunning "w3svc" # Is NPS configured as a proxy $boolNpsProxyConfigured = IsNpsProxyConfigured($xdNpsSvrCfg) if($boolNpsProxyConfigured -eq $true) { # If NPS is configred as a proxy, then check whether NAS is enabled in CRP $rrasConfigured = $rrasInstalled -and $rrasRunning -and ($allNasSourceTagCRP -or $rrasSourceTagCRP) $hraConfigured = $hraInstalled -and $iisInstalled -and $iisRunning -and ($allNasSourceTagCRP -or $hraSourceTagCRP) $hcapConfigured = $hcapInstalled -and $iisInstalled -and $iisRunning -and ($allNasSourceTagCRP -or $hcapSourceTagCRP) $dhcpConfigured = $dhcpInstalled -and $dhcpRunning -and ($allNasSourceTagCRP -or $dhcpSourceTagCRP) $tsgConfigured = $tsgInstalled -and $tsgRunning -and ($allNasSourceTagCRP -or $tsgSourceTagCRP) } else { # If NPS is NOT configred as a proxy, then check whether NAS is enabled # in CRP and NP $rrasConfigured = $rrasInstalled -and $rrasRunning -and ($allNasSourceTagCRP -or $rrasSourceTagCRP) -and ($allNasSourceTagNP -or $rrasSourceTagNP) $hraConfigured = $hraInstalled -and $iisInstalled -and $iisRunning -and ($allNasSourceTagCRP -or $hraSourceTagCRP) -and ($allNasSourceTagNP -or $hraSourceTagNP) $hcapConfigured = $hcapInstalled -and $iisInstalled -and $iisRunning -and ($allNasSourceTagCRP -or $hcapSourceTagCRP) -and ($allNasSourceTagNP -or $hcapSourceTagNP) $dhcpConfigured = $dhcpInstalled -and $dhcpRunning -and ($allNasSourceTagCRP -or $dhcpSourceTagCRP) -and ($allNasSourceTagNP -or $dhcpSourceTagNP) $tsgConfigured = $tsgInstalled -and $tsgRunning -and ($allNasSourceTagCRP -or $tsgSourceTagCRP) -and ($allNasSourceTagNP -or $tsgSourceTagNP) } $result = ($radiusClientEnabled -eq '1' -or $rrasConfigured -or $hraConfigured -or $hcapConfigured -or $dhcpConfigured -or $tsgConfigured) # Return the result of the rule return $result } # Function Description: # Checks if HRA is configured to point to atleast one valid Certificate Authority # # Arguments: # None # # Return Value: # Boolean. true if atleast one CA is configured, false otherwise function IsAtleastOneCAReachable { $CAReachable = $false $availableCAString = "" $configuredCAString = "" # Get a list of valid CAs $certConfig = CreateComObject "CertificateAuthority.Config.1" if ($certConfig -eq $null) { Write-Host "Error" } $FieldName = "Config" $caCount = $certConfig.Reset(0) for ($caIndex=0; $caIndex -lt $caCount; $caIndex++) { $caIndex = $certConfig.Next(); $availableCAString += $certConfig.GetField($FieldName) + "`n" } # HRA Registry Path where CA servers are added $key = "SOFTWARE\Microsoft\HCS\CAServers" $type = [Microsoft.Win32.RegistryHive]::LocalMachine $regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($type, $Srv) $regKey1 = $regKey.OpenSubKey($key) if($regKey1) { # For each CA configured, a registry key exists Foreach($sub in $regKey1.GetSubKeyNames()) { $keySub = $key + "\" + $sub $regKeySub = $regKey.OpenSubKey($keySub) # Check if any Value name is "Server" # This should contain the CA path Foreach($val in $regKeySub.GetValueNames()) { if($val -eq "Server") { $configuredCAString += $regKeySub.GetValue("$val") + "`n" } } } } # for each CA Configured on machine, check if it exists in available CAs $ArrayOfAvailableCA = $availableCAString.Split("`n"); foreach($availableCA in $ArrayOfAvailableCA) { $ArrayOfConfiguredCA = $configuredCAString.Split("`n"); foreach($configuredCA in $ArrayOfConfiguredCA) { if($availableCA -ne "" -and $configuredCA -ne "") { $availableCAwithSlash = "\\" + $availableCA if($availableCA -eq $configuredCA -or $availableCAwithSlash -eq $configuredCA) { $CAReachable = $true break } } } if($CAReachable -eq $true) { break } } # Return the result of the rule return $CAReachable } # Function Description: # Checks if IIS is configured to accept Http and Https requests # # Arguments: # $IISCfg: IIS configuration file # # Return Value: # ok - HRA accepts both HTTPS and HTTP communications # error - HRA does not accept both HTTPS and HTTP communications # warning - HRA accepts either HTTPS or HTTP communications function DoesHraAcceptsHttpHttps($IISCfg) { # Read the IIS configuration file and goto the appropriate node $iisConfigNode = $IISCfg.configuration.'system.applicationHost'.sites.site $resultHttps = $false $resultHttp = $false if($iisConfigNode) { $resultHttps = $true $resultHttp = $true # Among all configured websites, look for HRA foreach($iisSite in $iisConfigNode) { $foundHRASite = 0 $iisApplication = $iisSite.application foreach($_ in $iisApplication) { if($_.path -eq '/DomainHRA' -or $_.path -eq '/NonDomainHRA') { $foundHRASite = 1 } } # If HRA web-site is found, check if https traffic is accepted if($foundHRASite -eq 1) { $flagHraAcceptsHttp = 0 $flagHraAcceptsHttps = 0 $iisSiteBinding = $iisSite.bindings.binding foreach($_ in $iisSiteBinding) { if($_.protocol -eq 'http') { $flagHraAcceptsHttp = 1 } if($_.protocol -eq 'https') { $flagHraAcceptsHttps = 1 } } if($flagHraAcceptsHttps -eq 0) { # HRA website does not accept Https request $resultHttps = $false } if($flagHraAcceptsHttp -eq 0) { # HRA website does not accept Http request $resultHttp = $false } } } #endof foreach($iisSite in $iisConfigNode) } #endof if($iisConfigNode) if($resultHttps -and $resultHttp) { return "ok" } if(!$resultHttps -and !$resultHttp) { return "error" } if(!$resultHttps -or !$resultHttp) { return "warning" } return "ok" } # Function Description: # Ensure that the port is enabled and allows the incomming traffic # # Arguments: # $InputText: output of "netsh advf firewall" # # Return Value: # $RulePortEnabled: returns "true" if the port is enabled # function IsPortEnabled($InputText) { $result = $false $ruleEnabled = $FALSE $ruleAction = $FALSE # Split each line of netsh output # Checks the value of "Enabled" and "Action" keywords in input text foreach($_ in $InputText) { $abcd = $_.Split(" ", [StringSplitOptions]::RemoveEmptyEntries) # Ensure 'Enabled:' is set to "Yes" if($abcd[0] -eq "Enabled:") { $ruleEnabled = $FALSE if($abcd[1] -eq "Yes") { $ruleEnabled = $TRUE } } # Ensure 'Action:' is set to "Allow" if($abcd[0] -eq "Action:") { $ruleAction = $FALSE if($abcd[1] -eq "Allow") { $ruleAction = $TRUE } } } $result = $ruleEnabled -and $ruleAction # Return the result of the rule return $result } # Function Description: # Checks if Server’s firewall settings has exemption for both http and # https traffic # # Arguments: # None # # Return Value: # Boolean. true if Server’s firewall settings has exemption for both http # and https traffic, false otherwise # function CheckFirewallExemptionForHttpHttps() { $httpPortEnabled = (Get-NetFirewallRule | Where-Object {$_.InstanceID -Eq "IIS-WebServerRole-HTTP-In-TCP" -and $_.Enabled -Eq "True"}) -ne $null $httpsPortEnabled = (Get-NetFirewallRule | Where-Object {$_.InstanceID -Eq "IIS-WebServerRole-HTTPS-In-TCP" -and $_.Enabled -Eq "True"}) -ne $null # Return the result of the rule if($httpsPortEnabled -and $httpPortEnabled) { return "ok" } if(!$httpsPortEnabled -and !$httpPortEnabled) { return "error" } if(!$httpsPortEnabled -or !$httpPortEnabled) { return "warning" } return "ok" } # Function Description: # Checks if IIS server role is installed on HRA server # # Arguments: # None # # Return Value: # Boolean. true if IIS server role is installed on HRA server, # false otherwise # function IsIISComponentsInstalled() { $boolIISComponentsInstalled = $false # Initialize to perform querying Role information RoleQueryInitialize # Check if IIS is installed $boolIISComponentsInstalled = IsRoleInstalled "Web-Server" # Role Information obtained. RoleQueryShutdown return $boolIISComponentsInstalled } # Function Description: # Ensures that the certificate issued by StandAlone CA Server should be greater # than 20 minutes and less than 8 hours # # Arguments: # None # # Return Value: # Boolean. true if certificate lifetime is within the range, # false otherwise # function CheckCertificateLifeTime { #Run this rule only when standAlone CA is locally configured $result = $true # Read the registry $certLifeTime = (get-itemProperty HKLM:\Software\Microsoft\HCS\CAServers).CertificateLifeTime if($certLifeTime) { # Ensure the certificate lifetime is atleast 20 minutes and not greater # than 24 hours $result = ($certLifeTime -ge 20 -and $certLifeTime -le 1440) } # Return the result of the rule return $result } # Function Description: # This function appends the results to the xml file # # Arguments: # xml file which contains the results of rules # # Return Value: # None # function AppendToXML($document, $boolResult, $xmlNode) { if ($boolResult -eq $true) { $document.CreateNavigator().AppendChild("<$xmlNode>true") } else { $document.CreateNavigator().AppendChild("<$xmlNode>false") } } # Function Description: # This function creates a temp directory under the OS temp directory. # The directory is unique to the current session. # # Arguments: # None # # Return Value: # The path to the new temp directory. # function CreateTempSessionDir() { $ticks = (Get-Date).Ticks $sessionName = [String]::Format("BPA_NPAS_{0}", $ticks) $tempSessionDir = Join-Path -Path $env:TEMP -ChildPath $sessionName [Void](New-Item -Path $tempSessionDir -ItemType 'directory') return $tempSessionDir } # Function Description: # This function creates an nps configuration file using sdohlp.dll # Sdo generates a configuration file (xml) in a temp directory and the xml # is read. The directory and the temporary xml file are deleted before # the function exits. # # Arguments: # None # # Return Value: # An xml that was created using the configuration file that was generated by sdo. # function GetNpsConfiguration() { $tempSessionDir = $null try { # Create temp directory for the nps configuration $tempSessionDir = CreateTempSessionDir # export nps configuration $iaxXmlPath = Join-Path -Path $tempSessionDir -ChildPath 'ias.xml' $sdoType = [Type]::GetTypeFromCLSID("e9970fa4-b6aa-11d9-b032-000d56c25c27") $sdo = [Activator]::CreateInstance($sdoType) [Void]$sdo.Initialize($null) [Void]$sdo.GetIasService() [Void]$sdo.ExportConfiguration($null, $iaxXmlPath) # read nps configuration [xml] $xdNpsSvrCfg = Get-Content -Encoding UTF8 $iaxXmlPath return $xdNpsSvrCfg } catch { throw $_.exception } finally { if ($tempSessionDir -ne $null) { Remove-Item -Path $tempSessionDir -Recurse } } } # Function Description: # Entering function for NPS rules # This function calls NPS rules only when NPS component is installed # The rule results are appended to the xml file # # Arguments: # xml file which contains the results of rules # # Return Value: # None # function NPSMain($document) { # Initialize to perform querying Role information RoleQueryInitialize # Check if Certificate Authority is installed $ADCSCertAuthorityInstalled = IsRoleInstalled "ADCS-Cert-Authority" # Check if NPS is installed $isNPSInstalled = IsRoleInstalled "NPAS-Policy-Server" # Role Information obtained. RoleQueryShutdown if($isNPSInstalled -eq $true) { # Get NPS configuration [xml] $xdNpsSvrCfg = GetNpsConfiguration # Call the Rules and Append the results to XML file $boolResult = IsNpsServiceStatus AppendToXML $document $boolResult "NpsServiceStatus" $boolResult = IsNpsCrpEnabled($xdNpsSvrCfg) AppendToXML $document $boolResult "NpsCrpEnabled" $boolResult = IsNpsNetworkPolicyEnabled($xdNpsSvrCfg) AppendToXML $document $boolResult "NpsNetworkPolicyEnabled" $npsAuthenticationMethodText = CheckNpsAuthenticationMethod($xdNpsSvrCfg) if($npsAuthenticationMethodText.Length -gt 0) { $document.CreateNavigator().AppendChild($npsAuthenticationMethodText) } $boolResult = IsNasRunningLocally($xdNpsSvrCfg) AppendToXML $document $boolResult "NasRunningLocally" } } # Function Description: # Entering function for HRA rules # This function calls HRA rules only when HRA component is installed # The rule results are appended to the xml file # # Arguments: # xml file which contains the results of rules # # Return Value: # None # function HRAMain($document) { # Initialize to perform querying Role information RoleQueryInitialize # Check if Certificate Authority is installed $ADCSCertAuthorityInstalled = IsRoleInstalled "ADCS-Cert-Authority" # Check if HRA is installed $isHRAInstalled = IsRoleInstalled "NPAS-Health" # Role Information obtained. RoleQueryShutdown if($isHRAInstalled -eq $true) { # Call the Rules and Append the results to XML file $boolResult = IsAtleastOneCAReachable AppendToXML $document $boolResult "AtleastOneCAConfigured" # Get IIS configuration [xml] $IISCfg = get-content -Encoding UTF8 $env:windir\system32\inetsrv\config\applicationHost.config if($IISCfg) { $stringResult = DoesHraAcceptsHttpHttps($IISCfg) $document.CreateNavigator().AppendChild("$stringResult") } $StringResult = CheckFirewallExemptionForHttpHttps $document.CreateNavigator().AppendChild("$stringResult") $boolResult = IsIISComponentsInstalled AppendToXML $document $boolResult "IISComponentsInstalled" #Run this rule only when standAlone CA is locally configured if(IsStandAloneCARunning($ADCSCertAuthorityInstalled) -eq $true) { $boolResult = CheckCertificateLifeTime AppendToXML $document $boolResult "CertificateLifeTime" } } } # # ------------------ # FUNCTIONS - END # ------------------ # # # ------------------------ # SCRIPT MAIN BODY - START # ------------------------ # # Set the Target Namespace to be used by XML $tns="http://schemas.microsoft.com/mbca/models/NPAS/2009/11" NPSMain $NPSNode HRAMain $HRANode $doc # # ------------------------ # SCRIPT MAIN BODY - END # ------------------------ #