This blog is broken up into three parts:
In Part 2
I went over some code snippets, not the full source code that was used but enough for you to understand some of the more challenging sections. This final part will go through the Implementation of the Global Nav, in particular the various farm level settings that are required for the code to work throughout the farm. And as a reminder, this worked for me in this particular project, this may not be the only (or even best) way to accomplish this however it satisfied the requirements of the project and did not introduce any security vulnerabilities. Also, there were other considerations that impacted this implementation that are out of the scope of this article so if you are doing something similar do not assume that everything word for word here is what is needed for your project, be realistic and make sure to adapt these concepts to fit your actual needs.
A quick review of the design and some elaboration on it was we proceed. This global navigation is being implemented for a SharePoint 2010 collaboration portal. Important design notes that impact how this solution was implemented:
- Global Navigation needed to be implemented in multiple web applications, each running under a dedicated application pool service account
- Personalized Global Navigation needed to be displayed for every user of the site regardless of permissions, this included:
- Farm Admins
- Site Collection Admins
- Site Contributors
- Anonymous Users
- The security of the farm needed to be configured so that the code could query the various sites regardless of where the site exists (what Web Application, Site Collection, etc.)
This environment was a single farm and all of the collaboration sites lived under a single web application in various site collections. The example topology is as follows:
- Collaboration Web Application
- Test Community A Site Collection
- Test Community B Site Collection
- Internal Projects Site Collection
- Internal Project 1 Site
- Internal Project 2 Site
- Customer Projects Site Collection
- Project 3 Site
- Project 4 Site
The other pieces of the farm (Records Center, My Sites, etc.) are in various other web applications, each of which needed to use the global navigation solution to some extent
There are several places that need to have special permissions configured. Several of these were not my ideal choices, anytime you modify security for any reason you need to be cognizant of the impacts your changes are going to have on not only the SharePoint farm but to the network as a whole. In particular I did not like configuring other database accounts as db_owners but after extensive testing we could not find any security vulnerabilities that would cause problems. Make sure you work closely with the security administrator of the network before making any of these changes, especially in larger organizations some of these changes may be in violation of their security policies.
Add service accounts to the local administrators group on each WFE
First change was to add users to the local administrators group on each web front end (WFE). In order to query the farm to get the list of communities and projects for a given user the application pool account needed to have permissions to access the collaboration web application. By default only the account running the collaboration web application has permissions to query itself, the easiest way to fix this is to add all service accounts used for application pools to the local administrators group. This also needed to be done on *each WFE in the farm*, because technically a user may be logged in to WFE1 and the code may end up querying the structure from WFE2 depending on how the load balancing happened to kick in at that time.
This was the easiest way to accomplish this, and since the service accounts only had permissions to run services (as they should!) making them local administrators on the WFEs did not have a negative impact.
Configure service accounts in the User Policy of the Collaboration Web Application
Now that the service accounts can access the web application we must configure the web application to accept the query requests. Just because the service account can get to the web application as a local administrator on the WFE does not mean they can actually *do* anything once they are there. So with the collaboration web application selected you click on “User Policy” from the ribbon and add the users. For our implementation we used the following settings:
- Zones: (All Zones)
- Permissions: Full Control
- Account operates as System
Map the db_owner permission on each content database for each service account
Now that the service accounts could successfully get through SharePoint all that is left is to configure SQL Server to allow the service accounts to actually access the data. This is not something you normally think of (or at least I didn’t) because you expect SharePoint to manage all permission to content, since we are accessing content across web applications. Also if you think back to how SharePoint is designed you’ll remember that every Site Collection is assigned to one content database for a Web Application and that every Web Application can have one or more content databases. In this environment the Collaboration Web Application had 10 content databases, this means that we had to modify permissions for each of the 10 databases.
Why is this significant? Because if you ever need to add content databases to this web application for any reason you need to remember to make these changes on each one. It may seem obvious but it’s important to keep in mind because a year or two down the road when you add those content databases you probably will not remember why these special database permissions were made. Here are the generic steps for doing this (these are not click by click steps so if you are not familiar with SQL Server permissions refer elsewhere for more detailed instructions on doing this with SQL Server Management Studio)
- Verify that each of the service accounts are configured under security (this should be the default but it’s always best to double check)
- Go to properties for the login and modify user mappings
- For each content database used by the collaboration web application make the login as the db_owner.
The service account for the collaboration web application should already be a db_owner but any other ones should not be by default. This change I was really hesitant to make because for starters I don’t like modifying database permissions unless there is no other choice and more importantly it’s sort of a SharePoint rule of thumb to not touch databases that are used by SharePoint.
It may seem like a no-brainer but there are three distinct tests that I added to our test cases to verify that the global navigation was working. Since there are so many setup steps outside of SharePoint itself these really need to be included in every test of the application because especially if you have separate separate farm environments (DEV, QA, UAT, etc.) it’s really easy to make the change in one or two but miss another. And before these steps were documented the team (myself included) would forget one test and not realize it before elevating to the next environment. Don’t take short cuts (even though we all want to), document these and include them in the standard test cases for elevating code changes.
- Test that the Global Navigation appears properly in the Site that is hosting the Global Navigation List (in our scenario this was in a web application separate from the collaboration web application)
- Test that the Global Navigation appears properly from a community or project site within the collaboration web application
- Test that the Global Navigation appears properly in a web application separate from the previous tests (a separate records center web application in our environment)
- Test with a couple different user accounts to make sure users are only seeing communities/projects that they are authorized to collaborate on
This was an interesting challenge to work on because it seemed like something that should be fairly standard to implement but in reality I could not find a lot of good examples that pulled everything together like this. This is by no means a “click by click” tutorial on creating a custom Global Navigation however it should be enough of an overview to get you headed in the right direction when trying to create and implement your own.