Showing posts with label IIS. Show all posts
Showing posts with label IIS. Show all posts

Monday, June 5, 2017

URL Redirect Based on IP Address

As you are most likely aware, CRM/D365 has two URLs to access it when setup for IFD. The first URL, referred to as the “internal URL”, will allow authentication to be passed through and not display the ADFS login page for credentials. As the name suggests, this URL should only be available from within the network and not exposed out over the internet. The second URL, (not surprisingly) referred to as the “external URL”, will not pass through authentication and will display the ADFS login form for users to enter credentials. This URL is the one exposed out over the internet but is also available from within the network.

Customers often like the convenience of not having to enter credentials using the internal URL but do not like having two URLs to use. As a result, we are tasked with providing a solution to this dilemma. Back in the days of ADFS 2.0, we could easily handle this with a much simpler tweak in IIS of the ADFS server. Unfortunately, with the newer versions of ADFS no longer using IIS as its backbone this is no longer an option and a URL Rewrite rule now must be implemented on the CRM/D365 server. Here’s how:

1. Open IIS on the CRM/D365 Front End (web) Server and go to the URL Rewrite module of the CRM Website.


2. Click the link to “Add Rule(s)” and just select “Blank Rule” under Inbound rules.


3. Give the rule an applicable name and in the Match URL section, leave both the ”Requested URL” and “Using” fields as their defaults (shown in screen capture). In the “Pattern” field type in (.*).


4. This is where it gets fun. In the Conditions section, you will add three rules in the order shown below.

     a. For the first rule, change “crmorgname” to the actual name of your organization.
     b. For the second rule, change the pattern to match that of your internal IP range.
     c. Just enter the third rule as shown – no changes needed – ([^\.]*)\.(.*)


5. In the Action section, change the “Action type” to “Redirect” and for the Redirect URL enter your internal CRM/D365 URL followed by the syntax shown in the screenshot. Leave “Append query string” checked and set the Redirect type to “Permanent (301)”.


6. Apply the URL Rewrite rule and test it by going to the external URL from a machine that has an IP address matching that of the ranges specified on your network. If everything was setup correctly, the external URL will redirect to the internal URL and pass-through authentication will occur.

Friday, December 2, 2016

HTTP to HTTPS Redirect for CRM using Claims-Based Authentication and IFD

In some cases, our customers would like HTTP to HTTPS redirection setup for CRM when using Claims-Based Authentication and IFD. There are a number of articles and blogs out on the internet that use various methods to accomplish this (e.g. URL Rewriting) but I find that a lot are overly complicated if all you are looking to do is have the redirect functioning internally (you do not want port 80 open on your firewall anyways). Below is what I perceive to be the easiest method to achieving this – using the HTTP Redirection capabilities of IIS:

1. First we will need to install HTTP Redirection on the CRM Web Server if it is not installed already. In Server Manager, go to Add Roles and Features and choose to add the HTTP Redirection feature under the Web Server role.


2. Create two folders in a directory that you know will not be deleted. Name these folders something along the lines of “CRM Internal Redirect” and “CRM External Redirect”. Folder names and paths aren’t too important but in my example I just put them in the inetpub directory.


3. Next, go into IIS. Make sure to remove the HTTP (port 80) binding from the CRM site before proceeding with the next steps.

4. Since two URLs can be used to be accessed CRM when it is setup for Claims and IFD, we will need to create the redirects for both URLs. Begin by creating a new website in IIS for the Internal URL.
  • Site Name: Something descriptive such as “CRM Internal Redirect”
  • Physical Path: Browse to the CRM Internal Redirect folder created in step 2.
  • Binding Type: HTTP
  • IP Address: Unless you have multiple IP addresses on your server, you can leave this on All Unassigned. Otherwise, select the IP address used by CRM.
  • Port: 80
  • Host Name: This will your internal CRM URL which was configured when setting up Claims/IFD. If you are unsure of it, open the CRM Deployment Manager and go to properties. Select the Web Addresses tab and you should see your internal URL.

5. Just like step 4, create another new site in IIS – this time for the external URL:
  • Site Name: Something descriptive such as “CRM External Redirect”
  • Physical Path: Browse to the CRM External Redirect folder created in step 2.
  • Binding Type: HTTP
  • IP Address: Unless you have multiple IP addresses on your server, you can leave this on All Unassigned. Otherwise, select the IP address used by CRM.
  • Port: 80
  • Host Name: This will your exteransl CRM URL which was configured when setting up Claims/IFD. If you are unsure of it, this is the unique name of your CRM organization followed by the domain (e.g. orgname.domain.com).

6. You should now have IIS looking similar to this:


7. Click on your Internal Redirect site and open the HTTP Redirect module:


8. In the HTTP Redirect settings, check the box for “Redirect requests to this destination:” and then enter your internal URL with HTTPS:// prefixed. Leave the other boxes unchecked and status code at 302. Apply the configuration.


9. Now do the same for the External redirect site. Click on your External Redirect site and open the HTTP Redirect module. In the HTTP Redirect settings, check the box for “Redirect requests to this destination:” and then enter your external URL with HTTPS:// prefixed. Leave the other boxes unchecked and status code at 302. Apply the configuration.


That’s it. You should now be able to enter either of the CRM URLs with HTTP into a browser and have it redirected to HTTPS appropriately.

Thursday, November 3, 2016

Calling LoadLibraryEx on ISAPI filter DefaultAddonFilter.dll failed

I recently had an interesting issue with a client’s CRM 2011 to 2016 go-live. Following all of my upgrade work and initial testing, I typically like to reboot the CRM and SQL servers and then test again. In this particular instance, when the servers came back online I tested CRM again only to receive a lovely error message from Internet Explorer:

HTTP Error 500.0 – Internal Server Error

Calling LoadLibraryEx on ISAPI filter C:\Program Files\Microsoft Dynamics CRM\Server\bin\DefaultAddonFilter.dll failed.

After a fair amount of digging I noticed that the Visual C++ 2013 Redistributable (64-bit) was not present in the add/remove programs list on the CRM server. It seemingly uninstalled itself during the reboot because otherwise I would have had this issue pre-reboot. So, I went out and grabbed the installer package for Visual C++ 2013 Redistributable (64-bit) from MS (http://go.microsoft.com/fwlink/p/?LinkId=402059) and reinstalled it. After that and an IISReset, CRM began functioning as normal and everything retested everything successfully.

Unfortunately, I am at a loss as to why this happened – perhaps something to do with server patching. Also of note is that the redistributable did not remove itself from the SQL server.

Sunday, April 24, 2016

CRM and IIS Machine Keys

When you have multiple CRM web (front-end) servers splitting the load, requests can bounce between servers or they can be set to remain on the same server through the NLB/Firewall settings. The latter option is commonly referred to as “Sticky Sessions” or “Persistence”.

If requests bounce between servers (whether by design or by fault), you may notice issues when accessing certain functionality within CRM. Often it will be accompanied by the following error message in the event viewer:

Event code: 3012 
Event message: An error occurred processing a web or script resource request. The resource identifier failed to decrypt. 

Exception information: 
    Exception type: HttpException 
    Exception message: Unable to validate data.
   at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, Boolean useValidationSymAlgo, Boolean useLegacyMode, IVType ivType, Boolean signData)
   at System.Web.UI.Page.DecryptString(String s, Purpose purpose)
   at System.Web.Handlers.ScriptResourceHandler.ProcessRequest(HttpContextBase context, VirtualFileReader fileReader, Action`2 logAction, Boolean validatePath)

Basically what is happening is one server encrypted (validated) some of the traffic with an automatically generated key and another server received it but cannot decrypt it because it has different keys. These keys are known as “machine keys” and are found within IIS. By default, these keys are all set to generate automatically and no two are the same. When you are using multiple web servers, the machine keys need to be set statically and shared amongst them. Here is how to do this, starting on the first web server:

  1. Open IIS, select the Microsoft Dynamics CRM Website, and double-click “Machine Key”

  2. Uncheck the “Automatically generate at runtime” and “Generate a unique key for each application” boxes under both “Validation Key” and “Decryption Key”.

  3. Click “Generate Keys” on the right side of the screen.

  4. This will create new, random keys.

  5. Click apply.

  6. From here, repeat steps 1 and 2 on the remaining web servers. Instead of generating new keys as in step 3, copy and paste the keys generated from earlier into the remaining servers so that all servers have the same set of keys.
  7. Once keys on all servers are set and applied, reset IIS on all the boxes. That should do it.

Sunday, April 3, 2016

Host Header Configured on Selected Site Does Not Resolve to an IP Address that is Assigned to the Local System.

I was recently performing an in-place upgrade from CRM 2015 to CRM 2016 when during the system checks I received the following warning:

Host Header "notCRM.domain.com" configured on selected site does not resolve to an IP address that is assigned to the local system. This conflict must be reconciled for CRM Server to function properly. 



The fact that it was giving me a host header that did not pertain to the CRM website was odd so I took a look at IIS. What I discovered was that there was another website setup in IIS on the CRM Server. And that site had the site ID of 1.


As I was the original installer of CRM for this deployment, I knew that this site wasn’t here when CRM was installed. CRM originally had the site ID of 1, not this other site. Somebody had been in here messing around and changed the site IDs manually. After asking enough questions, I learned who did this and why. To make a long story short, their site needed to have the ID of 1. CRM, on the other hand, does not care so I rolled with the punches and decided I would work around this rather than cause a fuss.

From what I could deduce about the error message, the CRM installer was being told to look at the IIS website that had an ID of 1 to perform the upgrade on. I decided to switch the CRM site back to the ID of 1. To do this, you must first change the other site’s ID to a number not in use (e.g. 3, in my case). To do this, go into the site’s advanced settings.


After the other site was changed, I reverted the CRM site back to 1 and reset IIS.


The upgrade wizard will need to be restarted for it to pick up the change but once you make it back to the system checks, the warning should be gone.


The upgrade succeeded without issue but we weren’t done just yet. Since the other site needed to have the ID of 1, I needed to revert changes to the site IDs which in itself isn’t complicated. What was not taken into account was a registry key in HKLM\Software\Microsoft\MSCRM called “website”.


This registry key indicates which website directory in IIS CRM is using. Since CRM is using the ID of 2, this key needed to be switched to “LM/W3SVC/2”. In case you have been wondering what the ID controls, it is just an identifier used in the directory name for trace files and log files. It’s nothing critical that will not let CRM operate as normal.

By now you are probably thinking “Why didn’t you change this key rather than switching the site IDs to resolve the warning message during the upgrade?!?!” Well... it didn’t occur to me until afterward I completed the upgrade. Hindsight is 20/20!

Thursday, March 17, 2016

The Authentication Endpoint Username Was Not Found On The Configured Secure Token Service and Port 808

While not recommended, circumstances sometime present the need to install CRM and ADFS on the same server. If this is done on Windows Server 2012 R2, you will likely run into issues connecting anything through the discovery service such as the Outlook Add-In, Email Router, and Plugin Registration Tool. The error will read:

The authentication endpoint Username was not found on the configured Secure Token Service.

If taken literally, one would be tempted to go to the ADFS Configuration and enable the /adfs/services/trust/13/username endpoint as shown below:


DO NOT DO THIS! On the outside chance that it does actually fix the immediate issue it can cause further authentication problems and is NOT recommended – despite what some other blogs/forums may tell you.

Further investigation should eventually lead you to this error in the ADFS event viewer logs:

System.ServiceModel.AddressAlreadyInUseException: There is already a listener on IP endpoint 0.0.0.0:808. This could happen if there is another application already listening on this endpoint or if you have multiple service endpoints in your service host with the same IP endpoint but with incompatible binding configurations. —> System.Net.Sockets.SocketException: Only one usage of each socket address (protocol/network address/port) is normally permitted

With ADFS for Server 2012 R2, net.tcp port 808 is utilized for a function of the federation service. You may recall that port 808 is also used by CRM for its sandbox service so it’s easy to see the problem here. Port conflict! Luckily, the solution is rather simple. Just open a PowerShell prompt on the server and enter the following:

Set-ADFSProperties -nettcpport 809

(Note: In the above the command, 809 is just an example of a port that can be used and is not required. If something else is running over port 809 on your server, substitute it for some other number.)

After the command has been run, restart the ADFS service, IIS, and the email router service (if the email router was having the issue connecting) – to be on the safe side, you could just reboot the whole server. Give it another go and you should be in business! If you are wondering why this hasn’t been an issue with past versions of ADFS, it's because the federation services used to run on ports 1500 and 1501.