Saturday, 25 July 2015

SPApplicationAuthenticationModule: There is no Authorization header, can't try to perform application authentication.

This week we had an interesting issue with one of our SharePoint servers.

We have a two server farm, both servers are full servers that had been installed a couple of months ago and as far as I was aware both servers had been tested, so I was little bit surprised when the farm was tested in anger and we were getting a roughly ~20% failure rate in a process that uploads a document to SharePoint.

After a bit of digging we found that it was due to one of the SharePoint servers. 

We could not even log in to any of sites hosted on the farm if we hit this server. We simply would get a 401 unauthorized error. 

I know we also seem to have a load balancing issue but that's for another day.

Perhaps, unsurprisingly the logs did not show much, so I bumped them up to verbose and here's what we found:

Claims Authentication        SPIisWebServiceAuthorizationManager: Using identity '0#.w|dev\svc-spadm' as the actor identity.
Topology                     WcfReceiveRequest: LocalAddress: 'http://sp02.dev.local:32843/934e0061c6a94255b9ab9e6f2ba45325/SearchService.svc' Channel: 'System.ServiceModel.Channels.ServiceChannel' Action: 'http://tempuri.org/ISearchHealthMonitoringServiceApplication/GetQueryHealthMonitoringSettingsForComponents' MessageId: 'urn:uuid:f00ca305-b1d5-4454-85fa-5f83e7094518'
Monitoring                   Leaving Monitored Scope (ExecuteWcfServerOperation). Execution Time=154.973746663333
Monitoring                   Entering monitored scope (Request (GET:https://<site>)). Parent No
Logging Correlation Data     Name=Request (GET:https://<site>)
Claims Authentication        SPTokenCache.ReadTokenXml: Successfully read token XML ''.
Application Authentication   SPApplicationAuthenticationModule: There is no Authorization header, can't try to perform application authentication.
Authentication Authorization Non-OAuth request. IsAuthenticated=False, UserIdentityName=, ClaimsCount=0
Claims Authentication        Claims Windows Sign-In: Sending 401 for request 'https://<site>' because the user is not authenticated and resource requires authentication.
Monitoring                   Leaving Monitored Scope (Request (GET:https://<site>)). Execution Time=3.75103539695688
Claims Authentication        SPFederationAuthenticationModule.OnEndRequest: User was being redirected to authenticate.
Claims Authentication        Claims Windows Sign-In: Sending 401 for request 'https://<site>' because the user is not authenticated and resource requires authentication.

Clearly, It's not able to authenticate but why? I thought that the lack of authorization header was the clue but nothing I found in Google helped me and then I sort of had a flash of inspiration and decided to check whether the site had Windows Authentication enabled.

Bingo!!!!!  Windows Authentication is Disabled, no wonder nobody could log in :)


After I enabled it and restarted IIS, the second server started working :)

I didn't install SharePoint on these servers and I don't really have that much experience with SharePoint so I'm entirely sure who to blame here, our guys or Microsoft, but it seems to me that since one of the big things with Microsoft is integration with AD, it's just a bit daft that it doesn't turn Windows Authentication on for the SharePoint site by default. 

Maybe it does and it's something that we did.

At any rate, hope this helps.

Monday, 20 July 2015

Edit C# config file with PowerShell

So today we changed the organization name, too long to explain and all the external apps needed to have their app.config changed to reflect this change. This was across several environments so I thought it would probably be quicker to write a quick script to do it.

The script works for multiple files because they are on subfolders of a common folder, e.g.

Mycompany --> My App 1
                   --> My App 2
                   --> My App 3

It will of course work from say, c:, if you have your apps in different places but it might take a while to run. It will not work if they are in different drives though.

Here's the script:

param ($path, $keyname, $value)

if (-not($Path))
{
 write-host "Path is a mandatory parameter"
 break;
}

if (-not($keyname))
{
 write-host "KeyName is a mandatory parameter"
 break;
}

if (-not($value))
{
 write-host "value is a mandatory parameter"
 break;
}

$configfiles = ls -Path $path -Recurse -Include *config

foreach ($config in $configfiles)
{
 $doc = (Get-Content $config) -as [Xml]
 $obj = $doc.configuration.appSettings.add | where {$_.Key -eq $keyname}
 $obj.value = $value
 $doc.save($config)
}
Assuming the script has been named ChangeConfigFile.ps1, it can be invoked like this:
 ChangeConfigFile.ps1 -path "c:\program files\Apps\" -keyname "Organization" -value "NewOrg"

Saturday, 11 July 2015

Configure MS Dynamics CRM 2011/2013/2015 to use multiple Report Servers (SSRS)

This week I've had quite a bit of fun turning the resilience up to 11 for our production environment of MS Dynamics CRM 2013.

In this post I will discuss how to configure Ms Dynamics CRM 2013 to use multiple SSRS servers, thus ensuring that reporting functionality is as resilient as the rest of the system.

In order to achieve this we need to make changes to AD, the SSRS configuration and finally MS Dynamics CRM. 

It's worth pointing out that this could well be overkill for your system, and to a certain extent it is for ours, but the whole architecture must be resilient is the diktat from above so ...

Pre-Requisites:

  • 1 x Load Balancer (Distributing traffic to SSRS Servers on correct port, normally 80).
  • 1 x VIP.
  • 1 x DNS Record (For VIP above).
  • 2+ x SSRS Servers in a scale out deployment.
  • SSRS configured to use a domain account.
  • Permissions to set SPNs on your domain and edit at least ssrs service account.

My Setup:

DNS record is: CRMReports.dev.local
SSRS Service Account:  dev\svc-ssrs

1. Active Directory

The first thing to do is to set up an Service Name Principal for the account that's running the SSRS service, which can be done with the following commands:
setspn -S HTTP/<VIP FQDN> <SSRS Service account>
setspn -S HTTP/<VIP Name> <SSRS Service account>
So in my case:
setspn -S HTTP/CRMReports.dev.local dev\svc-ssrs
setspn -S HTTP/CRMReports dev\svc-ssrs
The next thing is to ensure that the account is enabled for delegation, so from Active Directory Users and Computers console.


Note that the delegation tab will only appear after an SPN has been set up for that account.

2. SSRS

The first thing to do in the report server, is to enable Kerberos authentication, which can be done by editing the rsreportserver.config file. This file is normally found in this directory: C:\Program Files\Microsoft SQL Server\MSRS11.MSSQLSERVER\Reporting Services\ReportServer\

Look for the Authentication section and enable Kerberos and Negotiate as below (I've commented out NTLM in case I wanted to go back)
<Authentication>
  <AuthenticationTypes>
   <RSWindowsKerberos/>
   <RSWindowsNegotiate/>
   <!--<RSWindowsNTLM/>-->
  </AuthenticationTypes>
  <RSWindowsExtendedProtectionLevel>Off</RSWindowsExtendedProtectionLevel>
  <RSWindowsExtendedProtectionScenario>Proxy</RSWindowsExtendedProtectionScenario>
  <EnableAuthPersistence>true</EnableAuthPersistence>
 </Authentication>
From the Reporting Services Configuration Manager, Click on Web Service URL and then click on Advanced


Click on Add as highlighted.


Enter the host header name, which will be the DNS Record for the VIP, in my case: crmreports.dev.local and click OK to accept.



Repeat this process for the Report Manager Url.

Once done repeat all steps on section 2 on the other report servers.

3. MS Dynamics CRM

The process is relatively simple and it involves editing the organization to point to the new report server dns, i.e. crmreports.dev.local in my case.

From the Deployment Manager, select organization and Disable your organization(s).


Click Edit Organization.


Set the new report server Url.


 Ensure that all checks are ok.


Congratulations, you now have a resilient reporting service for MS Dynamics CRM.