Tuesday, 18 June 2013

Dynamics CRM 2011 scalling multi-tenants across multiple SQL servers

Recently I've seen a few questions in the forums around placing new tenants on different SQL servers.
This is possible if you using an enterprise license, the option is available when you create a new tenant. You are not necessarily stuck to the SQL server where the MSCRM_CONFIG database is deployed, you could specify a different SQL server. You will need the same permissions as per the deployment guide.

However distributing tenants across multiple servers increases management, complexity and SQL licensing costs. Keep it simple, it's easier and cheaper to upgrade the hardware of one SQL server rather than having those resources distributed across multiple servers.

Creating New Organization
Open deployment manager click New Organization when it gets to the SQL server step specify a different SQL server











Click Next and specify the ReportServer as well













Note: you need local admin permissions on the SQL server and database permissions as per deployment guide.

The below diagram illustrates 4 Organizations distributed across multiple SQL servers and 2 of those with their own SQL Reporting Server.


























Conclusion
You can distribute tenants across multiple SQL servers including the SQL reporting services. A number of things can influence the decision to place tenants on different SQL servers:

  • Legal Reasons
  • Shared Resources
  • Size of databases with impact of backups 
  • Performance
  • Development and Testing

Friday, 7 June 2013

Dynamics CRM 2011 printing IFRAME

In the past I wrote an article on how to make iframes printable using the CRM print function, I was asked how to apply the same approach to CRM 2011, I had a look and CRM 2011 wraps the text inside another set of HTML elements, so we just need to make sure we return only text document.getElementById.textContent

This change is not supported as it changes directly an ASPX file, the file you have to change is custformprint.aspx located:

C:\Program Files\Microsoft Dynamics CRM\CRMWeb\_forms\print

For example if you have a SRS report loading in an IFRAME you just need  to set SRC="" url of the FRAME_ID:

document.getElementById('IFRAME_GoogleMap').src= "http://srsserver/reportserver?etc.....";
document.getElementById('IFRAME_GoogleMap').style.height = "400px";
document.getElementById('IFRAME_GoogleMap').style.width = "900px";

An example for Google Maps would be:


//does an initial check if the ID for the google map is set. (assuming you've used GoogleMap for the iframe)
if (document.getElementById('IFRAME_GoogleMap')) {
var url = "";
if (document.getElementById('address1_country_d') != null)
  url += (url == "" ? "" : ", ") + document.getElementById('address1_city_d').textContent;
if (document.getElementById('address1_city_d') != null)
  url += (url == "" ? "" : ", ") + document.getElementById('address1_city_d').textContent;
if (document.getElementById('address1_postalcode_d') != null)
  url += (url == "" ? "" : ", ") + document.getElementById('address1_postalcode_d').textContent;
if (document.getElementById('address1_line1_d') != null)
  url += (url == "" ? "" : ", ") + document.getElementById('address1_line1_d').textContent;
if (document.getElementById('address1_line2_d') != null)
  url += (url == "" ? "" : ", ") + document.getElementById('address1_line2_d').textContent;
if (document.getElementById('address1_line3_d') != null)
  url += (url == "" ? "" : ", ") + document.getElementById('address1_line3_d').textContent;

if (url != "")
{
  document.getElementById('IFRAME_GoogleMap').src= "http://maps.google.com/?q=" + url;
  document.getElementById('IFRAME_GoogleMap').style.height = "400px";
  document.getElementById('IFRAME_GoogleMap').style.width = "900px";
} else {
// If no data to pass to url, defaults to text only "No Results"
document.getElementById('IFRAME_GoogleMap_d').innerHTML= "No results";
}
}



Tuesday, 4 June 2013

dynamics CRM 2011 Data driven security Part II - Teams

This is part II of my previous post on data driven security where I mainly focus on Security Roles and Business Units architecture, you can read it here:
http://quantusdynamics.blogspot.com/2012/03/dynamics-crm-data-driven-security.html

On part II I will focus on Teams and it's concept around data sharing based on the same pyramid model used on Part I. I'm also covering how can teams leverage User management. In general Teams are great for:
  1. User Access Management and Security roles
  2. Sharing Data across Business Units
  3. Enhance collaboration

User Management Simplified with Teams
User management in CRM can become as complex as you want. The management side has been designed to be very basic, adding a user and assign a security role, this is what it takes to give a user access to CRM. However with multiple business units and multiple security roles and the lack of a built-in tool to check 'effective permissions' across the hierarchy of records and Business Units this could become very time consuming to manage and troubleshoot permission issues.

You could add users multiple security roles at the same time, however you can't remove them at the same time, if you assign 300 users the wrong security role, you will need to remove one by one the same security role or develop a tool to do this.

However we are lucky because we have teams which can be used like AD groups or sort of OU with GPOs. How would this work for User Management? When we create a Business Unit, CRM will automatically create a team with the same name as the Business Unit you just created and link it with the same Business Unit. On Part I, I've used a pyramid type graph to illustrate permissions, the below screenshot is the same graph but I'v added highlighted in yellow the corresponding teams. 






















On the above graph, all the default teams in yellow belong to their own BU, also all users moved to that BU will also be automatically added to the BU default team, this is great!! However the default teams are not assigned a security role, even better! :)

At this stage what you need to do is assign a security role to the default teams, the appropriate security role with permissions only for those Business Units. 

Now that all your default teams have a security role, if you didn't have users in the system, here is how it would work:
  1. Add one or multiple users to CRM and simply select the business unit you want to place the user on, don't assign security roles
  2. The user will inherit the Teams security role and it's permissions
  3. For those familiar with AD, this concept is similar to OU GPOs, every object you place on an OU is bound to the OU GPO's
You populated all users across all Business Units, now you have 50 Junior Engineers to move to the Global Engineers OU, this is how it would work:
  1. Select The users you want to move, and click 'Change Business Unit'
  2. Users will be automatically assigned the Global Engineers Security role because they are automatically added to the GlobalEngineers default team.
  3. Also users will be automatically removed from the JuniorEngineers team so they will also loose the JuniorEngineers Security role
  4. Conclusion: you didn't have to remove or add security roles

Assigning Users Business Unit































Sharing Data
On the pyramid model the idea is to isolate data from other departments and teams, only specific permissions would grant the Junior staff tier access data on the upper Business Units, the only permission setting that allows this to happen is the 'Organisation' level and this would open access to all BUs and not just the BU directly above, we don't want this to happen because it would break the pyramid model so we have to use teams to share data with groups of users or the entire BU.

Facts about teams:
  • Teams can only include users
  • Teams can include users of any Business Unit
  • You can share records with Teams from any Business Unit

To use teams to share records you create custom teams on the various business units, to be used as:
  1. Using Security roles to provide single BU access
  2. Object Access (record only)
Using Security roles
This method is familiar to us, we covered the concept on simplifying user management above. The team is assigned a security role so any user added to this team will also inherit the same security role, this is a great approach to give specific users in the junior tier, access to an external BU in this case the global engineers Business Unit.

Object Access
Instead of providing external BU access you may just want to share 1 or a few records with a number of users and teams, to do this you share data directly at the object-level (opportunity, account, etc).
  1. Create custom teams to group users
  2. On the record itself select Share and select the team you want to share the record with.
  3. This means any team from any BU could be added, and the record accessed by multiple users from multiple Business Units
  4. This avoided giving BU-wide permissions just to share one or a few records



The above diagram illustrates the concept of sharing records with Teams, team1 On the Junior Tier has been given share permissions on:
  • One Record on the Global Engineers BU
  • One Record on the Global Exports BU
A team from the Global Engineers BU has been also given access to a record on the Global Sales BU. I haven't illustrated the BU single acces because this is covered on the above diagram.
All users members of these teams are now able to view the records and if edit permissions were given able to write and collaborate.




















Conclusion
I hope this was useful, please leave your feedback or any questions you may have.

Wednesday, 3 April 2013

Dynamics CRM 2011 Default Organization Bug

On Multi tenant environments Dynamics CRM 2011 contains an annoying bug related to the default organization which breaks a number of things in CRM.

On a multiple tenant environment user accounts are managed under the MSCRM_CONFIG database, SystemUserOrganizations table. CRM keeps track of users configured on multiple tenants including the DefaultOrganization. The default organization it's the organization the user lands by default when typing the URL without specifying the organization he/she would like to access.

The issue with the default organization is that each time you configure a user on a new tenant, the DefaultOrganization field on the database gets updated with a new value, and this value is not necessarily the tenant that you just added the user on, it rotates, and this causes a number of things to break in CRM:


  1. Help Server URL
  2. Web resources with direct calls to iframes
  3. Exporting Error Rows from an import job
  4. The administrator yellow bar alerting to assign user roles











To fix the problem, set the user default organization to the correct one.

You can use the following SQL query to find users default organization:






Monday, 18 March 2013

Dynamics CRM 2011 recover deleted Active Directory user accounts

Some times user accounts in CRM get out-of-synch with Active Directory and this could be related with:
  • AD account deleted and re-created
  • AD restores
  • Or anything else that would change the objectGUID in AD
The most common is deleted accounts in Active directory. E.g. people returning to the same company, which previously used CRM and the account has been disabled, AD admins deleted the account and now create a new account with the same details in AD; if you try to enable the user account in CRM, you will get an error because CRM can't find the same AD GUID:

External Error - No such Object on Server
















If you haven't disabled the account, you don't have to follow the next instructions, simply change the username field to a random test account and save, and change it back again to the user account you want to configure and save, this will update the user GUID and the AD SID in CRM. However if you have disabled the account you need to do the following steps.

Building the LDAP Query
The process is simple and it involves finding out the new objectGUID and objectSID in AD with an LDAP query and update the CRM database manually.

You can use any LDAP tool, for simplicity I find LDP tool simple to use and also available with windows 2008 R2 servers.

Simply search for ldp on the windows search box, or type on the command prompt c:\ldp and press enter

1. With the tool open go to the menu Connection and select connect, type the LDAP/DC server














2. When connected, you need to bind the session to a user account, to perform the search under that user context. Go to the Menu Connection > Bind











3. I've used the currently logged on user, but you can specify any account you want.















4. When you bind the session to an account you should get a successful message like the below message:

0 = ldap_set_option(ld, LDAP_OPT_ENCRYPT, 1)
res = ldap_bind_s(ld, NULL, &NtAuthIdentity, NEGOTIATE (1158)); // v.3
{NtAuthIdentity: User='NULL'; Pwd=; domain = 'NULL'}
Authenticated as: 'DOMAIN\your_account'.

5. Now that you connected, go to Browse > Search















6. On the Search window, you type the Base DN (Distinguish Name) which is the location of the account in AD, select the scope: Base, and the most important select the attributes you want to view, in this case you only need:

objectGUID
objectSID













7. Click Run and the below screenshot shows the account new GUID and SID.

























Compare the results with CRM
Compare these values with the ones in the CRM database:


select DISTINCT sub.fullname, sub.ActiveDirectoryGuid, sua.AuthInfo, sua.UserId
from SystemUserbase sub
inner join MSCRM_CONFIG.dbo.SystemUserOrganizations suo ON
        suo.CrmUserId = sub.SystemUserID
inner join MSCRM_CONFIG.dbo.SystemUserAuthentication sua ON
        sua.UserId = suo.UserId
where sub.DomainName = 'domain\username'






























Update CRM database
From the screenshots above, we can see the information match with what it's in CRM and in AD. if the AD object changes in AD e.g. account deleted and re-created; the GUID and SID would be different in the LDAP results; with the results provided from the LDAP query, update the CRM database manually:





Conclusion
The above process applies to most scenarios when an account had the objectGUID and objectSID updated in AD and CRM becomes out-of-sync with AD, however if you didn't disable the account you are in a better position to simply change the domain username to a dummy account and revert it back, but when you disable accounts you can't enable it back again, you can then use the above process to recover the CRM accounts.

Hope this helps and please leave your feedback.

Wednesday, 6 March 2013

Dynamics CRM 2011 Multiple organizations Asychronous Service Optimization

On a multi tenant environment where organisations are used as a way of isolating data e.g. sales team vs IT staff; the Asynchronous services will not balance workload across organizations evenly; if you have one organisation generating more workflows than others, it's likely to have an impact on the other organisations Asynchronous jobs; e.g. taking longer to execute workflows, or data imports.

The below diagram illustrates the Asynchronous service workload on this scenario:




On the above diagram the bottleneck it's on the Sales Organization taking 59% of the Asynchronous processing time delaying the execution of the IT staff Organization workflows.

To avoid these type of bottlenecks we can limit the number of system jobs the Async service picks up per organization by setting the AsyncSelectMaxItems with the following PowerShell commands:

add-pssnapin Microsoft.Crm.Powershell
$itemSetting = new-object 'System.Collections.Generic.KeyValuePair[String,Object]'("AsyncSelectMaxItems",100)
$configEntity = New-Object "Microsoft.Xrm.Sdk.Deployment.ConfigurationEntity"
$configEntity.LogicalName="Deployment"
$configEntity.Attributes = New-Object "Microsoft.Xrm.Sdk.Deployment.AttributeCollection"
$configEntity.Attributes.Add($itemSetting)
Set-CrmAdvancedSetting -Entity $configEntity

The following diagram illustrates how the asynchronous service would balance the system jobs per organization:


Thursday, 14 February 2013

Dynamics CRM 2011 Outlook client how to track items on multiple mailboxes stores

I came across this a few times and I don't think it's widely documented, if you want someone to track emails, contacts or other items on other users mailbox, this is possible with CRM client, you can make this possible with two steps and no permissions in AD are needed:

You would normally receive the below error when trying to track an item on other users mailbox:



To make tracking items on other users mailbox possible, you need to access the users items/mailbox, you do this by asking the user to:
  1. First delegate control over the mailbox via the delegate permissions
  2. Secondly by giving you folder permissions so you can expand the items in your Outlook.
  3. Add the user's mailbox to Outlook and you ready to track other users emails, contacts etc..
 Note: The created record owner will be the original users mailbox but the 'Created By' will match the actual person that tracked the record.

Delegate Access
In Outlook go to File > Account Settings > Delegate Access


 





















Search the user in the Address Book > Click Add > and Ok:









Assign the Delegate Permissions:





















Mailbox Folder Permissions
From the folders view, Right-click the Mailbox and select Folder permissions:
 










On the Folder permissions screen you don't have to give Owner permissions you can customize it, what is important is that the user gets permissions to read:






























Now Add the user's Mailbox to your Outlook
On the Folder Permission screenshot above, on the General Tab > click Advanced and you see the below Screenshot.























Use the Add button to Add the Users mailbox by typing the User's Name and click OK, and the mailbox is added to your navigation folders.


Conclusion
And this should be enough to let you track items other users mailboxes. Hope this was useful and happy tracking. :)