Pages

Tuesday, November 17, 2020

PowerShell Script for enabling security permissions inheritance on Active Directory User Accounts

One of the most common questions I still get asked when it comes to Skype For Business is when an administrator attempts to edit an account but receives the following error:

Active Directory operation failed on "dc1.contoso.local". You cannot retry this operation: "Insufficient access rights to perform the operation

image

This error has been around since Lync Server 2010 and the two ways around it are:

  1. Use PowerShell to edit the account
  2. Enable Inheritance for the Active Directory account

Most administrators would prefer to opt for #2 as this would allow the account to be configured in the GUI so what needs to be done is to go into the Security properties of the account, click on Advanced button, then click on Enable inheritance so that the account inherits permissions:

image

This isn’t too much effort for one or two accounts but not very practical in the 10s, 100s or 1000s. The following are PowerShell scripts that allows to better identify and configure these accounts:

List Accounts and their Inheritance Status and Enable Accounts that have Inheritance disabled

$ou = 'ou=User Acccounts,ou=Contoso Organization,dc=contoso,dc=local'

$userslist = Get-ADUser -ldapfilter “(objectclass=user)” -searchbase $ou

foreach($account in $userslist)

{

# Bind the accounts

$ou = [ADSI](“LDAP://” + $account)

$sec = $ou.psbase.objectSecurity

if ($sec.get_AreAccessRulesProtected())

{

$isProtected = $false ## turn on inheritance

$preserveInheritance = $true ## retain inherited permissions

$sec.SetAccessRuleProtection($isProtected, $preserveInheritance)

$ou.psbase.commitchanges()

Write-Host “$account is now enabled for inheritance”;

}

else

{

Write-Host “$account already has inheritance enabled”

}

}

Export Accounts and Inheritance Status to CSV

$CSVexportPath = 'C:\temp\AccountInheritanceStatus.csv'

$ou = 'ou=User Acccounts,ou=Contoso Organization,dc=contoso,dc=local'

$userslist = Get-ADUser -ldapfilter “(objectclass=user)” -searchbase $ou

foreach($account in $userslist)

{

# Bind the accounts

$ou = [ADSI](“LDAP://” + $account)

$sec = $ou.psbase.objectSecurity

$UPN = $account.UserPrincipalName

$name = $account.name

$DistinguishedName = $account.DistinguishedName

#Store the information from this run into the array

[PSCustomObject]@{

UPN = $account.UserPrincipalName

Name = $account.name

DistinguishedName = $account.DistinguishedName

InheritanceEnabled = $sec.get_AreAccessRulesProtected()

} | Export-Csv $CSVexportPath -notype -Append

}

List Inheritance Status to Table

$ou = 'ou=User Acccounts,ou=Contoso Organization,dc=contoso,dc=local'

$userslist = Get-ADUser -ldapfilter “(objectclass=user)” -searchbase $ou

foreach($account in $userslist)

{

# Bind the accounts

$ou = [ADSI](“LDAP://” + $account)

$sec = $ou.psbase.objectSecurity

$UPN = $account.UserPrincipalName

$name = $account.name

$DistinguishedName = $account.DistinguishedName

#Store the information from this run into the array

[PSCustomObject]@{

UPN = $account.UserPrincipalName

Name = $account.name

DistinguishedName = $account.DistinguishedName

InheritanceEnabled = $sec.get_AreAccessRulesProtected()

} | Format-Table -AutoSize

}

Tuesday, November 10, 2020

Attempting to create a Availability Group Listener after successfully creating a SQL Server 2019 Availability Group fails with: "The WSFC cluster could not bring the Network Name resource with DNS name..."

Problem

You’re attempting to create a Availability Group Listener after successfully creating a SQL Server 2019 Availability Group but receive the following error:

TITLE: Microsoft SQL Server Management Studio

------------------------------

Create failed for Availability Group Listener 'PRD_TX_Listener'. (Microsoft.SqlServer.Smo)

For help, click: https://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&ProdVer=16.100.44091.28+(SMO-master-A)&EvtSrc=Microsoft.SqlServer.Management.Smo.ExceptionTemplates.FailedOperationExceptionText&EvtID=Create+AvailabilityGroupListener&LinkId=20476

------------------------------

ADDITIONAL INFORMATION:

An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)

------------------------------

The WSFC cluster could not bring the Network Name resource with DNS name 'PRD_TX_Listener' online. The DNS name may have been taken or have a conflict with existing name services, or the WSFC cluster service may not be running or may be inaccessible. Use a different DNS name to resolve name conflicts, or check the WSFC cluster log for more information.

The attempt to create the network name and IP address for the listener failed. If this is a WSFC availability group, the WSFC service may not be running or may be inaccessible in its current state, or the values provided for the network name and IP address may be incorrect. Check the state of the WSFC cluster and validate the network name and IP address with the network administrator. Otherwise, contact your primary support provider. (Microsoft SQL Server, Error: 19471)

For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&ProdVer=15.00.2000&EvtSrc=MSSQLServer&EvtID=19471&LinkId=20476

------------------------------

BUTTONS:

OK

------------------------------

image

===================================

Create failed for Availability Group Listener 'PRD_TX_Listener'. (Microsoft.SqlServer.Smo)

------------------------------

For help, click: https://go.microsoft.com/fwlink?ProdName=Microsoft+SQL+Server&ProdVer=16.100.44091.28+(SMO-master-A)&EvtSrc=Microsoft.SqlServer.Management.Smo.ExceptionTemplates.FailedOperationExceptionText&EvtID=Create+AvailabilityGroupListener&LinkId=20476

------------------------------

Program Location:

at Microsoft.SqlServer.Management.Smo.SqlSmoObject.CreateImpl()

at Microsoft.SqlServer.Management.SqlManagerUI.AGListenerConfigurationNewModeViewData.DoWorkCore(AGListenerController controller)

at Microsoft.SqlServer.Management.SqlManagerUI.AGListenerConfigurationControl.OnRunNow(Object sender)

at Microsoft.SqlServer.Management.SqlMgmt.PanelExecutionHandler.Run(RunType runType, Object sender)

at Microsoft.SqlServer.Management.SqlMgmt.SqlMgmtTreeViewControl.DoPreProcessExecutionAndRunViews(RunType runType)

at Microsoft.SqlServer.Management.SqlMgmt.SqlMgmtTreeViewControl.ExecuteForSql(PreProcessExecutionInfo executionInfo, ExecutionMode& executionResult)

at Microsoft.SqlServer.Management.SqlMgmt.SqlMgmtTreeViewControl.Microsoft.SqlServer.Management.SqlMgmt.IExecutionAwareSqlControlCollection.PreProcessExecution(PreProcessExecutionInfo executionInfo, ExecutionMode& executionResult)

at Microsoft.SqlServer.Management.SqlMgmt.ViewSwitcherControlsManager.RunNow(RunType runType, Object sender)

===================================

An exception occurred while executing a Transact-SQL statement or batch. (Microsoft.SqlServer.ConnectionInfo)

------------------------------

Program Location:

at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType, Boolean retry)

at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(StringCollection sqlCommands, ExecutionTypes executionType, Boolean retry)

at Microsoft.SqlServer.Management.Smo.ExecutionManager.ExecuteNonQuery(StringCollection queries, Boolean retry)

at Microsoft.SqlServer.Management.Smo.SqlSmoObject.ExecuteNonQuery(StringCollection queries, Boolean includeDbContext, Boolean executeForAlter)

at Microsoft.SqlServer.Management.Smo.SqlSmoObject.CreateImplFinish(StringCollection createQuery, ScriptingPreferences sp)

at Microsoft.SqlServer.Management.Smo.SqlSmoObject.CreateImpl()

===================================

The WSFC cluster could not bring the Network Name resource with DNS name 'PRD_TX_Listener' online. The DNS name may have been taken or have a conflict with existing name services, or the WSFC cluster service may not be running or may be inaccessible. Use a different DNS name to resolve name conflicts, or check the WSFC cluster log for more information.

The attempt to create the network name and IP address for the listener failed. If this is a WSFC availability group, the WSFC service may not be running or may be inaccessible in its current state, or the values provided for the network name and IP address may be incorrect. Check the state of the WSFC cluster and validate the network name and IP address with the network administrator. Otherwise, contact your primary support provider. (.Net SqlClient Data Provider)

------------------------------

For help, click: http://go.microsoft.com/fwlink?ProdName=Microsoft%20SQL%20Server&ProdVer=15.00.2000&EvtSrc=MSSQLServer&EvtID=19471&LinkId=20476

------------------------------

Server Name: BMA-PROD-SQL1

Error Number: 19471

Severity: 16

State: 0

Line Number: 1

 ------------------------------

Program Location:

at Microsoft.SqlServer.Management.Common.ConnectionManager.ExecuteTSql(ExecuteTSqlAction action, Object execObject, DataSet fillDataSet, Boolean catchException)

at Microsoft.SqlServer.Management.Common.ServerConnection.ExecuteNonQuery(String sqlCommand, ExecutionTypes executionType, Boolean retry)

image

Solution

This error is typically displayed if the Cluster Name Object (CNO) in Active Directory does not have permissions to create and read the listener computer object. The CNO name can be found in the Failover Cluster Manager:

image

To correct the issue, simply navigate to the OU containing CNO, which would be where it will attempt to create the listener computer object, right click on the OU and select Delegate Control… to launch the Delegation of Control Wizard:

image

Add the CNO computer object:

image

Select Create a custom task to delegate and click Next:

image

Select This folder, existing objects in this folder, and creation of new objects in this folder then click Next:

image

Select General and Creation/deletion of specific child objects, then locate the following and select the following:

  • Read all properties
  • Create Computer objects
  • Delete Computer objects
image

With the CNO computer object granted the respective permissions, the listener should now create successfully:

image

Attempting to create a SQL Server 2019 Availability Group fails with the error: "The local node is not part of quorum and is therefore unable to process this operation."

Problem

You attempt to create a new SQL Server 2019 Availability Group after configuring a Windows Failover Cluster:

image

… but the following error is presented:

TITLE: Microsoft SQL Server Management Studio

------------------------------

   The local node is not part of quorum and is therefore unable to process this operation. This may be due to one of the following reasons: 

• The local node is not able to communicate with the WSFC cluster.

• No quorum set across the WSFC cluster.

  For more information on recovering from quorum loss, refer to SQL Server Books Online. 

(Microsoft.SqlServer.Management.HadrTasks)

-----------------------------

BUTTONS:

OK

------------------------------

image 

Clicking on the Show details button displays the following:

===================================

The local node is not part of quorum and is therefore unable to process this operation. This may be due to one of the following reasons:

• The local node is not able to communicate with the WSFC cluster.

  • No quorum set across the WSFC cluster.

For more information on recovering from quorum loss, refer to SQL Server Books Online.

   (Microsoft.SqlServer.Management.HadrTasks)

------------------------------

Program Location:

at Microsoft.SqlServer.Management.Hadr.CreateAvailabilityGroupWizardController.CreateDataModel()

at Microsoft.SqlServer.Management.Hadr.CreateAvailabilityGroupWizardController.Initialize()

at Microsoft.SqlServer.Management.TaskForms.SqlWizardController.Microsoft.SqlServer.Management.TaskForms.ISqlWizardController.Initialize(ISqlWizardManager wizardManager)

at Microsoft.SqlServer.Management.TaskForms.SqlWizardManager.LoadWizardController()

at Microsoft.SqlServer.Management.TaskForms.SqlWizardManager.Initialize(String moniker, IContext context, ISqlWizardInfo wizardInfo)

at Microsoft.SqlServer.Management.ActionHandlers.ShowWizardActionHandler.RunTaskForm(IContext context)

at Microsoft.SqlServer.Management.ActionHandlers.DialogBasedActionHandler.RunTaskFormThread(Object contextObject)

image 

Solution

One of the common cause of this error is if the Enable Always On Availability Groups configuration for the SQL Server Services was turned on before you have installed and configured the Windows Failover Cluster:

image

If this is the case, simply disable the Enable Always On Availability Group option, restart the SQL Server Services, re-enable the option, and then restart the service:

image

The New Availability Group should now launch and allow you to create the Always On Availability Group:

imageimageimageimage

The New Availability Group should now launch and allow you to create the Always On Availability Group:

imageimageimage

Monday, November 2, 2020

Configuring X-Content-Type-Options and Permissions-Policy for Citrix ADC / NetScaler to score A on Security Headers for Exchange OWA

I’ve recently been involved with a few projects involving security vulnerabilities from penetration scans and one of the clients were asked to secure their Exchange OWA portal load balanced behind a Citrix ADC so that 2 of the 6 headers that are identified to be missing from the Security Headers (https://securityheaders.com/) scan are addressed:

  • X-Content-Type-Options
  • Permissions-Policy
image

Please refer to my previous blog post for instructions on how to implement the other headers identified to be present in the scan above:

Securing a Citrix ADC (formally known as NetScaler VPX) to score an A rating on Security Headers - March 2020
http://terenceluk.blogspot.com/2020/02/securing-citrix-adc-formally-known-as.html

X-Content-Type-Options

The X-Content-Type-Options header is fairly easy to implement as it is described in Citrix’s knowledge base article:

How to create rewrite policy for content security headers , XSS protection, HSTS, X-Content-Type-Options & Content-Security-Policy.
https://support.citrix.com/article/CTX233095

The following are the CLI commands:

add rewrite action rw_act_insert_Xcontent_header_Policy insert_http_header X-Content-Type-Options "\"nosniff\""

add rewrite policy rw_pol_insert_XContent_Policy TRUE rw_act_insert_Xcontent_header_Policy

bind lb vserver mail.college.bm_external -policyName rw_pol_insert_XContent_Policy -type RESPONSE -priority 120 -gotoPriorityExpression NEXT

image

The following is the Rewrite Action in the Citrix ADC / NetScaler GUI:

image

The following is the Rewrite Policy in the Citrix ADC / NetScaler GUI:

image

With the Rewrite Action and Policy in place, and having the policy bound to the virtual server, the scan should now return the header as being present:

image

Permissions-Policy

The Permissions-Policy, which replaces the Feature Policy, isn’t as straight forward as Citrix does not have a KB for the implementation of this header. However, Scott Helme provides a very detailed explanation for this header:

Goodbye Feature Policy and hello Permissions Policy!
https://scotthelme.co.uk/goodbye-feature-policy-and-hello-permissions-policy/

The following are the CLI commands to create the Rewrite Action, Policy and bind it to the virtual server:

add rewrite action rw_act_insert_Permissions_Policy insert_http_header Permissions-Policy "\"vibrate=(self), sync-xhr=(self \'https://<owa.domain.com>\')\""

add rewrite policy rw_pol_insert_Permissions_Policy "HTTP.RES.HEADER(\"Permissions-Policy\").EXISTS.NOT" rw_act_insert_Permissions_Policy

bind lb vserver mail.contoso.com_external -policyName rw_pol_insert_Permissions_Policy -type RESPONSE 110 -gotoPriorityExpression NEXT

image

The following is the Rewrite Action in the Citrix ADC / NetScaler GUI:

image

The following is the Rewrite Policy in the Citrix ADC / NetScaler GUI:

image

With the Rewrite Action and Policy in place, and having the policy bound to the virtual server, the scan should now return the header as being present:

image

**Note that the reason why the score in the screenshot above is A rather than A+ is because the Content-Security-Policy header configured contains the ‘unsafe-inline’ in the script-src directive. I have yet to successfully omit ‘unsafe-inline’ for sites such as a Citrix Gateway or Exchange OWA without causing the login page to fail to load.

image

PowerShell script for clearing the msRTCSIP-DeploymentLocator attribute when it is populated with "SRV:"

As mentioned in my previous posts:

Enabling user for Teams Enterprise Voice fails with: "Management object not found for identity"
http://terenceluk.blogspot.com/2020/10/enabling-user-for-teams-enterprise.html

… a user who has previously been enabled for an on-premise Skype for Business Server may still have the msRTCSIP-DeploymentLocator attribute populated with the value SRV: even after they have been removed from the on-premise SfB Server.

image

Having this value in their user account would prevent them from being enabled for Enterprise Voice in Microsoft Teams and the quick resolution for this would be to remove the attribute, for and AD Connect sync, then try enabling them again.

imageimageimage

This solution may be viable for a few accounts but not practical when the amount goes up to the 100s or 1000s so I decided to create a few PowerShell cmdlets to automate the process.

Find SfB Enabled with msRTCSIP-DeploymentLocator Configured Accounts

Get-ADuser -Properties msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled -Filter {msRTCSIP-DeploymentLocator -like "*" -and msRTCSIP-UserEnabled -eq $true } | Select UserPrincipalName,msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled

Find SfB Enabled with msRTCSIP-DeploymentLocator Configured as SRV: Accounts

Get-ADuser -Properties msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled -Filter {msRTCSIP-DeploymentLocator -eq "SRV:" -and msRTCSIP-UserEnabled -eq $true } | Select UserPrincipalName,msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled

Find SfB Disabled with msRTCSIP-DeploymentLocator Configured as SRV: AND empty msRTCSIP-PrimaryHomeServer Accounts Export as CSV

Get-ADuser -Properties msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled -Filter {msRTCSIP-DeploymentLocator -eq "SRV:" -and msRTCSIP-UserEnabled -notlike '*' -and msRTCSIP-PrimaryHomeServer -notlike '*'} | Select UserPrincipalName,msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled | Export-CSV C:\temp\SRVaccounts.csv

Find SfB Disabled with msRTCSIP-DeploymentLocator Configured as SRV: AND empty msRTCSIP-PrimaryHomeServer Accounts and Clear value

**The following cmdlet modifies accounts and I would recommend to export them to a list and review prior to making the changes**

Get-ADuser -Properties msRTCSIP-DeploymentLocator,msRTCSIP-PrimaryHomeServer,msRTCSIP-UserEnabled -Filter {msRTCSIP-DeploymentLocator -eq "SRV:" -and msRTCSIP-UserEnabled -notlike '*' -and msRTCSIP-PrimaryHomeServer -notlike '*'} | Set-ADUser -Clear msRTCSIP-DeploymentLocator

The following are the output of some of the cmdlets above.

image

Behavior of Microsoft Teams voicemail feature with when the user's mailbox is on an on-premise Exchange Server

Now that working from home has become more popular for organizations during the pandemic, many of the clients I work with have decided to deploy Microsoft Teams’ Direct Routing feature that allows users to receive and make calls out via the PSTN network. A few of the larger organizations I’ve had the opportunity to work with have still kept their messaging on-premise for various reasons and one of the most common complaints I’ve received is the voicemail notification. I still remember researching how it worked for on-premise Exchange Server deployments and found I had to combine several sources to understand what worked and didn’t so this blog post serves as a quick summary of the behavior.

The short story of the type of experience a user with an on-premise Exchange Server mailbox would have when they are enabled for Enterprise Voice in Teams is that voicemail notifications are sent to them via email. The email originates from Office 365 Exchange Online and delivered to the on-premise Exchange server and into the user’s mailbox via SMTP. The only issue I’ve seen where users do not receive this notification is if the organization uses a SPAM service such as Mimecast and it is not configured to allow Office 365 IP addresses for relay (https://community.mimecast.com/s/article/Maintaining-Authorized-Outbound-Addresses) and therefore the emails are stuck in the Exchange Online’s queue failing to be delivered.

Users with an on-premise Exchange Server mailbox will see the following message on their smartphones when they receive a voicemail but unable to do anything else within the menu:

We have your voicemail covered.

You can listen to voicemail or read the transcript.

imageimage

Clicking into the Voicemail menu in the Calls section will display the following:

We can’t get your voicemail right now

Please check back soon.

image

All of the above are default behaviors of a Teams user with an on-premise Exchange Server mailbox and the only way around this is to migrate them to Exchange Online.

More information about this can be found at the follow Microsoft documentation:

Set up Cloud Voicemail for Exchange Server Mailbox Users
https://docs.microsoft.com/en-ca/microsoftteams/set-up-phone-system-voicemail#set-up-cloud-voicemail-for-exchange-server-mailbox-users

Hope this helps anyone looking for an explanation of what works and what doesn’t when a user isn’t on Exchange Online.

Successfully logging onto Citrix StoreFront displays the message: "There are no apps or desktops available to you at this time."

Problem

Users have complained that they no longer see published apps and desktops after successfully logging onto Citrix as they only see the message:

There are no apps or desktops available to you at this time.

image

Reviewing the Citrix Delivery Services event logs on the Citrix StoreFront server displays the following errors:

None of the Citrix XML Services configured for farm Controller are in the list of active services, so none were contacted.

Log Name: Citrix Delivery Services
Source: Citrix Store Service
Event ID: 4012
Level: Error

image

Failed to launch the resource 'Controller.GP' as it was not found.

Log Name: Citrix Delivery Services
Source: Citrix Store Service
Event ID: 28
Level: Warning

image

None of the Citrix XML Services configured for farm Controller are in the list of active services, so none were contacted.

Log Name: Citrix Delivery Services
Source: Citrix Store Service
Event ID: 4012
Level: Error

image

Solution

The most important entry in the event logs written for this issue could easily be missed because the entry that provides the cause of the issue is actually labeled as Information. Continuing to move to earlier logs will reveal the following entry indicating that the SSL certificate on the Delivery Controller has expired:

The Citrix XML Service at address svr-ctxdc-02.ccs.int:443 has failed the background health check and has been temporarily removed from the list of active services. Failure details: An SSL connection could not be established: The server sent an expired security certificate. The certificate *.ccs.int, *.ccs.int is valid from 10/29/2018 9:37:20 AM until 10/28/2020 9:37:20 AM.. This message was reported from the Citrix XML Service at address https://svr-ctxdc-02.ccs.int/scripts/wpnbr.dll[UnknownRequest].

image

You would not be able to see this entry if you are reviewing the logs in the Administrative Events, which does not display Information entries.

image

To correct the issue, simply issue a new SSL certificate to replace the expired certificate on the Delivery Controller (or controllers if there are more than one), then update the bindings in IIS Manager:

imageimage

Successfully updating the SSL certificate will re-establish communication between the StoreFront server and the Delivery Controller(s).