Part of Microsoft’s Windows Azure strategy is offering organizations the choice to port and run portions of their existing applications in the cloud while continuing to utilize on-premise software. This is a compelling strategy with many variations which are easy to implement using Windows Azure and related web technologies. As with everything software, though, there are some issues to consider; I’ll share lessons I learned involving security and Silverlight while porting the UI of an existing business application to Windows Azure. Everything I discuss is equally applicable to any cloud hosted Silverlight or AJAX application which consumes on-premise services due to cross domain and cross security zone restrictions.
Specifically let’s start by discussing:
Here’s the setup, let’s say you’ve read patterns & practices Windows Azure Guidance and Windows Azure Security Guidance. Both are very informative and enabled you to successfully move your traditional ASP.NET application to Windows Azure. You followed the “Securing aExpense” section of Phase 1: Getting to the Cloud to switch your application’s configuration from Windows Authentication to claims-based. What you have matches the App Scenario – ASP.NET to AD with Claims as show in this diagram:
[Image from http://azuresecurity.codeplex.com/wikipage?title=ASP.NET%20to%20AD%20with%20Claims&referringTitle=Claims%20Scenarios]
This is passive, WS-Federation authentication. Essentially your web.config file is configured such that the WSFederationAuthenticationModule causes ASP.NET to automatically redirect a client’s browser to your ADFS server. The ADFS issues a SAML token then redirects back to your ASP.NET application. WSFederationAuthenticationModule validates the token then writes an encrypted cookie which SessionAuthenticationModule decrypts upon each web request and populates the ClaimsPrincipal object.
OK, management is impressed with how quickly you got the app to run in the cloud and they decide to revisit your recommendation for using Silverlight and AJAX to spice up the UI. They ask you to add a new feature which obtains data from an existing on-premise REST service, WCF service, XML file, or whatever. You code up two prototypes, one with Silverlight and the other using AJAX. You hit F5 and Visual Studio launches your application in the Azure Development Fabric but something is wrong. The exception thrown by Silverlight identifies the issue, the web site hosting the service needs a clientaccesspolicy.xml file. You’ve encountered the most common of Silverlight’s network security access restrictions, so common in fact that the number of blogs about it obscures searching and finding the more important details about access restrictions published on MSDN which explain why the restrictions are desirable. Browsers also implement similar access restrictions which AJAX applications need to consider; see the exceptions thrown by XMLHttpRequest’s open() method and IE’s XDomainRequest documentation.
Anyhow most of the sample clientaccesspolicy.xml files on the internet have “*” everywhere and you unknowingly copy the file, that’s exactly what I did the first time. You contact the team who runs the existing service and ask them to put your xml file on their server. They’ve never seen a clientaccesspolicy.xml file before, it is just an xml file and the servers are sitting safe on-premise behind the firewall, so they unknowingly deploy your file. You hit F5, the Azure Development Fabric launches, and everything works great this time. In a follow-on article I’ll explain why clientaccessplicy.xml files with “*” in them are dangerous and especially so for security token services (STS) which issue tokens for active requestor, WS-Trust federation.
Wow, working with the other group was easy. Now all you need to do is upload your package to your Azure account, go show management the prototypes, and start the weekend early. Finally this job is starting to resemble what was described during the interview!
Out to the cloud you deploy, but again something is wrong; so much for starting the weekend early. To troubleshoot you decide to upload the code to an on-premise server running the “on-premise” version of the web.config file to see what happens when Azure is taken out of the picture; amazingly it works. So is there a problem with Azure? Did you just discover a difference between the Development Fabric and the cloud?
No, you’ve just encountered another Silverlight security restriction which blocks cross-zone calls. Your Azure hosted application is in the Internet security zone while your on-premise service is in the Local Intranet security zone. The URL Access Restrictions in Silverlight topic on MSDN discuss this. Most developers do not know about these restrictions until they start hosting Silverlight on Azure and attempt to access an on-premise service, such as is done while requesting a token from your corporate STS for active federation. Luckily you found this article!
The easiest way to determine if a cross-zone restriction is blocking the call is to access the service URL’s in IE and see what security zone the browser’s status bar indicates. To make the calls succeed you can configure IE to rezone the URL’s via settings under Tools, Internet Options, Security, Local intranet, Sites, Advanced. That’s fine during development but for production you’ll need to get the settings pushed to users automatically via Group Policy settings. Take a look at the Group Policy Settings Reference then find File Name = inetres.admx and Policy Setting Name = Site to Zone Assignment List. In the reference I downloaded these settings were on the Administrative Template tab, rows 1594 and 1595.
Another option is to run your Silverlight application out-of-browser and select “Require elevated trust when running outside the browser”. This lifts Silverlight’s sandbox restrictions. The Silverlight Security Overview discusses the aspects of Silverlight impacted by this setting.
WCF RIA Services avoid the cross domain and cross security zone restrictions by implementing a design pattern where the RIA domain services are colocated in the same web site as the Silverlight XAP file and AJAX pages. From the client’s perspective it is only calling a single site. The RIA domain services then orchestrates calls to on-premise services and databases. Using RIA Services, or its design pattern, to get at your data is probably the best solution to what I described above but comes at the price of extra network hops, latency, and complexity if the on-premise services you’re calling are secured.
In next article we’ll discuss more details about securing the on-premise service calls, dive into the dangers of “*” everywhere clientaccesspolicy.xml files, and I’ll explain how a domain naming standard can pull parts of the cloud into your local intranet security zone.