Lars Nielsen's Discoveries

July 30, 2012

SharePoint 2010 Search Troubleshooting

Filed under: Search,SharePoint,Troubleshooting — Lars Nielsen @ 7:02 pm
Tags:

Here are some troubleshooting tips when you hit problems setting up SharePoint 2010 Search Content Sources

If you’re using SSL (HTTPS) for the URL of your site then you need to use SPS3S not SPS3 as the prefix for the address in the content source.  Thanks to this thread for that tip.  If you don’t then you get an error in the crawl log:

The object was not found

You might also see this error when trying to crawl My Sites and/or when using SPS3 or SPS3S:

Access is denied. Verify that either the Default Content Access Account has access to this repository, or add a crawl rule to crawl this repository. If the repository being crawled is a SharePoint repository, verify that the account you are using has “Full Read” permissions on the SharePoint Web Application being crawled. ( HttpStatusCode Unauthorized The request failed with HTTP status 401: Unauthorized. )

In this case you need to allow the crawler content account permissions access to the User Profile Service Application.  Thanks for this post from Cory Roth for the answer

In Manage Service Applications select the User Profile Service Application

Click Administrators button

Add an entry for the search crawler Content Access account and give it Retrieve People Data For Search Crawlers permission

Search Crawl account on User Profile Service

July 13, 2012

SharePoint Designer, Reporting Services and UAG

Filed under: Development,SharePoint,Troubleshooting — Lars Nielsen @ 6:51 pm
Tags: , ,

I set up a SharePoint 2010 environment with Forefront UAG and Kerberos authentication throughout, all via SSL.  Now our SharePoint sites can be published out to the Internet with a protection barrier.  It all works fine for general browsing and opening documents.  And now finally I  have solved the problem of people having to authenticate again when opening documents from SharePoint…  With UAG they authenticate once when they browse to the site and then that’s it.  They can click to open documents from SharePoint, edit documents,  and even open the document library in Explorer view without having to authenticate again.

So having got all that working, I thought: let’s push the envelope a bit and see what happens when we try to use Reporting Services reports in SharePoint Integrated mode over UAG.   Not only that, but the SSRS reports we were trying to deploy into SharePoint included hard links on the report which reference the Report Server URL directly using the ReportServerURL built-in field in the link.  So for example with regular Reporting Services your report server URL might be http://MyServer/ReportServer and then dynamicallythe report creates a link like this:

http://MyServer/ReportServer?https://myportal.domain.com/Reports/Myreport.rdl&rs:Command=Render&MyParameter=Something

That’s fine when the browser can get to http://MyServer but of course once you’re out on the Internet that URL won’t work because there’s no public DNS entry for it.  So the link will break.  You can work round this because SharePoint creates a proxy address for the Report Server which you can use instead.  The URL is like this:

https://myportal.domain.com/_vti_bin/ReportServer

OK so then this should work as the link to the report:

https://myportal.domain.com/_vti_bin/ReportServer?https://myportal.domain.com/Reports/Myreport.rdl&rs:Command=Render&MyParameter=Something

There was also a requirement for a link that directly exports the report as a PDF, using an additional query string parameter:

&rs:Format=PDF

So I thought just tag that on to the end of the main URL like this:

https://myportal.domain.com/_vti_bin/ReportServer?https://myportal.domain.com/Reports/Myreport.rdl&rs:Command=Render&MyParameter=Something&rs:Format=PDF

But when I tried this URL, instead of downloading a PDF file of the report I just got a 500 internal server error from the web server.  I tried adding an entry in my HOSTS file for myportal.domain.com to bypass the UAG server and connect directly to the SharePoint web server.  Then the link above worked OK and the download PDF popup box appeared.  So UAG is doing something to break that link.

The SharePoint ULS logs pointed to the problem.  Every time I got a 500 errors from Reporting Services I say errors like this in the logs:

Unexpected error in ProcessRequest: System.Net.CookieException: The ‘Value’=’2012,6,13,13,14,27,56,0’ part of the cookie is invalid.     at System.Net.Cookie.VerifySetDefaults(CookieVariant variant, Uri uri, Boolean isLocalDomain, String localDomain, Boolean set_default, Boolean isThrow)     at System.Net.CookieContainer.Add(Cookie cookie)     at Microsoft.ReportingServices.SharePoint.Soap.Utils.SetRelayRequestCookies(HttpWebRequest relayRequest, HttpRequest clientRequest)     at Microsoft.ReportingServices.SharePoint.Soap.RSBaseHttpHandler.ProcessRequest(HttpContext context) 2b0eb16a-e8df-4d6c-8cb8-3741011353f4

It looked as if there was some problem with a cookie with a value of 2012,6,13,13,14,27,56,0 – some kind of time stamp apparently.  I had a look at the site in Chrome and used the developer toolbar Resources tab to look at the cookies in the browser.  Sure enough there was a cookie called dwLastDetectionTimestamp with a value that looked like a timestamp with commas between the values.  I deleted this cookie manually from the browser and tried the URL again and it worked.  So it was that rogue cookie that was causing Reporting Services to fail.

Chrome Cookies

It turns out UAG injects a Javascript file called logoff.js into every web request that passes through it.  This Javascript file is what does the work of checking whether the activity timeout period has run out and whether to warn the end user of an impending auto-timeout.  It enters into an infinite recursive loop, checking that value of the cookie and if it’s null, setting it to be the current date and time, then checking to see if a certain period of time has elapsed.  Reporting Services for some reason inspects that value of this cookie but cannot understand it (because it belongs to UAG) and thus throws an exception.

The way round this is to override the UAG script and redefine that loop function to set the value of that cookie to be some non-null value, which deletes it from the cookie set.  I created a standard page in SharePoint to act as the target for Reporting Services reports.  The SharePoint page itself had a single Content Editor web part in it with a reference to my Javascript file which looks like this:

/* Strip the dwLastDetectionTimestamp cookie off the request and redirect it to the Report Server proxy */
function compareTimeStamps()
{
   $.cookie("dwLastDetectionTimestamp", null, { path: '/' }); // delete cookie
}

$(document).ready(function() {
  var FullUrl = window.location.href;
  var QueryString = FullUrl.split("?")[1];
  var NewServerUrl;
  if ((QueryString.match(/^https:\/\/myportal.mydomain.com.+$/ig))) {
    NewServerUrl = "https://myportal.mydomain.com/_vti_bin/ReportServer?" + QueryString;
    $.cookie("dwLastDetectionTimestamp", null, { path: '/' });
    window.location.href = NewServerUrl;
  }
});

To use this script you’ll need to have <script> tag references to JQuery and to the JQuery cookie plugin.  And of course you need to replace myportal.domain.com with the address of the root of your SharePoint site. The code in the script strips out the query string from the incoming request URL and checks to see if it’s a request to Report Server, and if so then it removes the cookie and redirects the browser to the Report Server proxy with the same query string.  Note the regular expression test (QueryString.match) which prevents the redirect happening when you are editing the page.  It will only redirect if the first thing after the question mark is a URL string.  The script also redefines the compareTimeStamps function within the script that UAG injects.  This is the function that is called continuously to check for auto-timeout.

In a report or a SharePoint page when you need to create a link that would use the URL of Report Server, you use instead the URL of the SharePoint page that holds this script. Add any query string parameters as required just as if you were going to the Report Server directly.

June 15, 2012

Kerberos, Reporting Services and SharePoint across domains

Filed under: Administration,SharePoint,Troubleshooting — Lars Nielsen @ 8:21 pm
Tags: , ,

Here’s another small piece of knowledge to add to the body of info about Kerberos, SharePoint and Reporting Services Integration.  Like so many others, I spent ages recently trying to get Kerberos to work with SharePoint 2010. Through trial and error, I found one point that I haven’t seen mentioned anywhere else, so I thought I’d write it up here. This applies when you are trying to use Constrained Delegation in Kerberos. If you’re wondering what that is, or if you’re starting out down the road of Kerberos Authentication in SharePoint 2010, then here are the resources I found most useful:

It’s worth reading about what Kerberos is and what it does.  This video is a good first introduction.

The best starting point is this Microsoft White Paper – get it and read it very carefully!  It actually has 90% of what you need to know, but in some places I found it ambiguous or confusing. The white paper describes a number of Kerberos tools for debugging, like Kerbtray, although I ended up using just KLIST in a command window most of the time which lists your Kerberos tickets, along with Fiddler to track the requests and responses from the web server. Another great resource are Adam Saxton’s blogs on Kerberos – for example this one.  It walks you through the process with plenty of screen shots.

If (OK, when) you hit problems, you need to enable Kerberos error logging on all the SharePoint servers in the farm. You may as well do it on all the servers so then turn it off on all of them once everything is working OK. Note that you will start to see “errors” that may not be causing you any real problems – especially KDC_ERR_PREAUTH_REQUIRED errors.  Don’t worry if your event logs aren’t completely error-free.

Cross Domain Issues

The main point of this post is to cover the case where you’re working across domains, something that is not really covered in detail in the White Paper above. In this case there’s more work to do.  For example you need to establish trust between the domains even if they are in the same forest.

Duplication

You also need to bear in mind the Forest Search Order and how this affects which KDC is hit first.  If you find that everything works from one domain, but not from another, start looking for duplicate SPN’s (or even duplicate Constrained Delegation settings – see below) in the different domains.  You need to get rid of any duplicates.  Learn the SETSPN command – it has new options in Windows 2008.  I found that the SETSPN -XF command which searches for duplicates sometimes didn’t work across the forest – it missed some duplicates and reports what look like false positives relating to other services.  I  prefer to use SETSPN -L to search for duplicates explicitly on each of the relevant SharePoint and Reporting Services service accounts.  Remember to use the -S option in SETSPN rather than -A.

Delegation

One point that is in the White Paper above, but if often missed elsewhere, is if you’re using Kerberos Constrained Delegation.  Constrained Delegation is configured when, in the Delegation tab in Active Directory Users and Computers, you select the option “Trust this user for delegation to specified services only”.  Basic Delegation is set up when select “Trust this user for delegation to any service”.

In that case, you need to set up delegation (using the HTTP service) from the SharePoint Application Pool account to the Reporting Services cluster. That’s in addition to the delegation to the fully qualified and NETBIOS names for the SharePoint web application URL’s. So for example if your SharePoint site is at intranet.mydomain.com and your Reporting Services cluster is at rs.mydomain.com then, on the Application Pool identity account, you need to set up delegation for:

  • HTTP/intranet.mydomain.com
  • HTTP/intranet
  • HTTP/rs.mydomain.com
  • HTTP/rs

But you only need to set SPN’s on that same account for:

  • HTTP/intranet
  • HTTP/intranet.mydomain.com

If you don’t put in delegation to the Reporting Services cluster address, then you’ll find the authentication to SharePoint works OK, and you can see your ticket in KLIST.  But things start to break when you try to use Reporting Services features within SharePoint. For example, when you try to edit the data source in SharePoint, you might see an error:

The request failed with HTTP status 401: Unauthorized.

And when you try to deploy a report from Business Intelligence Developer Studio, you’ll be challenged to authenticate with your username and password again in a Reporting Services Login box.  Then the deployment will fail.

Don’t Mix Basic and Constrained Delegation

This is something I haven’t found documented anywhere so far.  If you use Constrained Delegation on the SharePoint Application Pool identity account, you must also use Constrained Delegation on the Reporting Services service account.  You cannot use Constrained Delegation on the App Pool identity and Basic Delegation on the Reporting Services account.  I’m guessing that the opposite is true – i.e. if you use Basic Delegation on the Reporting Services service account you must also use it on the App Pool identity account.  The White Paper above suggests that this is an issue if you need to switch away from Kerberos later in the authentication chain (protocol transition).  But I found even if everything is pure Kerberos, the same thing still applies.

If you get this wrong then you find that reports will deploy OK from Business Intelligence Developer Studio, but will not run.  If you edit the data source in SharePoint and set it to use Windows Authentication, and then click the Test Connection button, you’ll see an error:

Logon failed for NT AUTHORITY\ANONYMOUS

You’ll see similar errors on SQL Server in the SQL log files. This is because the connection between Reporting Services and SQL Server has lost your credentials, because the delegation didn’t pass the credentials that far.

Again according to the White Paper above, you can use Basic Delegation (everywhere) if you want to connect to a data source outside the domain where the Reporting Services service is running.   But if you set Basic Delegation on the Application Identity account then that might limit your ability to connect from that web application to services other than Reporting Services, like Excel Services or authenticated RSS feeds.  Using Constrained Delegation (everywhere) is more flexible, but it will prevent Reporting Services from passing your credentials to data outside its domain (even within the same forest).

[Updated – additional notes below]

SQL Analysis Services as a Data Source

As well as using Reporting  Services to report from SQL Database tables or views, you can use SQL Analysis Services as a data source as well.  If you want to do this, the Kerberos configuration becomes more complicated   But it’s the same principle.  You set MSOLAPSvc.3 SPN’s on the SQL Analysis Services service account (assuming you’re using a dedicated service account) as described in the White Paper above.  If you’re using a named instance of SQL Server for Analysis Services then you also need to set SPN’s on the SQL Browser service account.  Then you set the delegation on the Reporting Services service account to be the SPN’s on the SQL Analysis Services account.  This allows Reporting Services to pass your credentials to Analysis Services.

You also need to ensure that the connection string in the data source (RSDS file in SharePoint) contains SSPI=Kerberos.  Otherwise when you edit the data source in SharePoint and click on the Test Connection button you will see a red error message:

The connection either timed out or was lost

If you don’t put in the right SPN’s for Analysis Services then when you click the Test Connection button you will see a red error message:

Authentication Failed

 

May 15, 2012

Down for Maintenance page for SharePoint sites

Filed under: Administration,SharePoint — Lars Nielsen @ 8:36 pm
Tags: , ,

Here’s a quick tip if you need to take a SharePoint site down for maintenance, or if you have some incident that takes it down.  For example, if you’re restoring a site collection, you can put up a friendly “down of maintenance” message when people visit the site.  You can put a “no access” lock on the site collection in Central Admin, but that won’t help if you’re restoring a site collection because it needs to be unlocked.  And when the site collection is deleted, visitors will just get a timeout error in their browser if they try to go to a page within the site collection.

If you can turn off access to a whole web application then there’s a another way.  This might apply for example to an Intranet that has its own web application.  You can put a special file called app_offline.htm in the IIS root folder of the site (the same folder than contains the web.config file).  This file can contain HTML, CSS and Javascript (but no ASP.NET code – it is pure HTML).  We use it to provide links to external applications and services that are not part of SharePoint, but which people frequently access via the Intranet.   In this way people can still find those applications even if the Intranet is down.

When you do this, IIS will return the app_offline.htm for every web requestwithin the web application domain.  So don’t use <script> or <link> tags to reference other files in the same folder.  Keep everything within the HTML code of the page itself.

This is an ASP.NET facility, but it works fine with SharePoint as well.  Because it’s ASP.NET it doesn’t rely on SharePoint at all. So even if your farm is down completely (database server down, for example) then this technique will still work. You need to deploy this file manually on the appropriate web server(s) into the right IIS folder on the file system.

May 1, 2012

Easy way to move, copy or add bulk multiple accounts in SharePoint groups

Filed under: Administration,SharePoint — Lars Nielsen @ 7:10 pm
Tags: ,

Have you ever wanted to work with a bunch of users in a SharePoint group? For example:

  • Move multiple users from one SharePoint group to another?
  • Export the details of users within a SharePoint group?
  • Get a list of accounts to populate a SharePoint group?

Here’s an easy way to work with the members of a SharePoint group in bulk. Suppose for example you want to move or copy a load of users from one group to another, if you have Outlook 2007 or higher.

First browse to the membership of the SharePoint group in Site Settings – People and Groups.

Then click the “Select All” checkbox on the top left. Or select the users you want.

Select Actions – Email Selected Users

Email Selected Users

Outlook will open a new e-mail message with the e-mail addresses of those accounts you selected.

Outlook Message

Copy the e-mail addresses in the Send To text area and paste them into Notepad

Close the new e-mail message (don’t send it!!)

Browse to the SharePoint group that you want to add those users into

Select New – Add Users

In the text area paste the e-mail addresses you copied from the Outlook message

Add New Users

Click the “Check Names” icon and they should all resolve to actual AD accounts

Resolve New Users

Click OK and the users will be added to the group.

This is a great way to harvest a list of accounts for membership of a group.  If you’ve ever asked customers or colleagues to send you a list of people who should be made members of a group, what do you get?  An e-mail with a list of people names, nicknames, shortened names…   And what’s the betting that those names translate to 3 people in your corporate AD with the same name and you can’t work out which one it is?  Or it’s “William” instead of “Bill”, etc.

Solve all those problems by asking your customer to create an e-mail message with all the appropriate people in the “To” box, copy the e-mail addresses out of the box, and paste them into the body of an e-mail.  Then all you need to do is to copy and paste the list of e-mail addresses into the Add Users box as above.

« Previous PageNext Page »

Create a free website or blog at WordPress.com.