Updates from Richard Prodger Toggle Comment Threads | Keyboard Shortcuts

  • Richard Prodger 11:23 am on July 3, 2012 Permalink | Reply  

    New Azure Web Sites and SSL (HTTPS) 

    The newly released Azure Web Sites doesn’t yet allow you use your own SSL certificates. You can secure the channel by using their *.azurewebsites.net cert, but you can’t stop someone using plain old “http”. In order to secure your whole site, add the following to your web.config to force redirection to https.

      <system.webServer>
        <validation validateIntegratedModeConfiguration="false" />
        <rewrite>
          <rules>
            <rule name="Redirect HTTP to HTTPS" stopProcessing="true">
              <match url="(.*)"/>
              <conditions>
                <add input="{HTTPS}" pattern="^OFF$"/>
              </conditions>
              <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="SeeOther"/>
            </rule>
          </rules>
        </rewrite>
      </system.webServer>

    If you’re using ASP.NET MVC (V2 onwards), you don’t need this, you can simply add [RequireHttps] to any of your controller actions.

    Advertisements
     
  • Richard Prodger 11:04 am on April 26, 2012 Permalink | Reply  

    GAP in the clouds! 

    I’ve devoted quite a lot of my time in recent months leading the development of a really cool Azure hosted tracking and visualisation platform. Known as the Global Alerting Platform, or GAP for short, it offers a way for any GPS enabled device with comms to be tracked and monitored. The reason for this post, is to share that it is being used for an exciting trip up Mt. Everest. We were approached by Iridium some time ago to develop the protocol for a new satellite phone. Known as the Extreme, this hanset will be carried by the Everest team and tracked by GAP.

     
  • Richard Prodger 2:28 pm on March 8, 2012 Permalink | Reply  

    Azure Table Storage has missing rows in query result (continuation tokens) 

    I had a small table of 10 rows where the PartitionKey and RowKey where both unique. After querying this table every few seconds for several months, quite happily, it suddenly started returning only 4 rows. After a sleepless night trying to figure it out, it turns out that any query that doesn’t specify both a partition key and a row key can return a continuation token. I wasn’t specifiying a PartitionKey as I wanted all rows. Azure, in its wisdom, moved my data around (as it is entitled to do) and split the table across storage nodes. Consequently, Azure is now returning 4 rows along with a continuation token for the rest. I had to change my code to handle the tokens. There are a few ways to do this in .NET. Either hard code it yourself or use the TableServiceExtensionMethods.AsTableServiceQuery

    If you want to avoid continuation tokens, a query must address a single entity completely.

    BEWARE! – If you forget to do this, your code may work today but may fail tomorrow without you having any knowledge or control.

    Thanks to Richard for his diagnostics help.

     
  • Richard Prodger 2:39 pm on September 14, 2011 Permalink | Reply  

    Windows Azure Privacy Statement 

    I’m often asked about the Data Protection Act in the UK and how that relates to hosting personal data outside of the European Union. Well here is a snippet from the Windows Azure Platform Privacy Statement that should help. I suggest reading the whole thing and make sure your laywers are aware of what you are doing.

    “Microsoft abides by the Safe Harbor framework as set forth by the U.S. Department of Commerce regarding the collection, use, and retention of data from the European Union, the European Economic Area, and Switzerland.”

     
  • Richard Prodger 9:40 pm on July 18, 2011 Permalink | Reply  

    Using the Windows SMTP Server in Azure 

    If you want to use the built in SMTP server in an Azure role then there are a few hoops you need to jump through. Firstly, you need a reliable way to install it each time a role instance comes up. This is done with a startup task in your ServiceConfiguration.csdef file:

    <Startup>
      <Task commandLine="Startup.cmd" executionContext="elevated" taskType="simple" />
    </Startup>

    The Startup.cmd needs to do 2 things. First, it uses powershell to install the SMTP server and secondly, it uses a vbscript file to configure the SMTP server once installed. Let’s look at the powershell code first. You need to tell the powershell environment to allow unsigned scripts before running the installation script.

    powershell -command "Set-ExecutionPolicy Unrestricted"
    powershell .\InstallSmtpServer.ps1

    The InstallSmtpServer.ps1 contains the following:

    Import-Module Servermanager
    Add-WindowsFeature SMTP-Server

    The first line imports the module for configuring the server and the second line add the SMTP server. This can take a couple of minutes to run. Having installed the SMTP server, we now need to configure it. There are 2 things we need to do here. By default the SMTP server will not allow any relaying, so if you want to send email from this server then you have to add 127.0.0.1 to the grant list. Next, you have to add one or more alias domains if you want to receive emails. There are several ways to do this, but the simplest is to use good old VB script and the ADSI objects from the good ol’ days. Here is the script:

    Option Explicit
    Dim iisSmtpServer, relayIpList, domainObject, newDomain,alias
    
    alias = "myapp.cloudapp.net"
    ' Create an instance of the SmtpServer object that represents the default smtp server.
    Set iisSmtpServer = GetObject("IIS://localhost/smtpsvc/1")
    ' Get the current relay ip list
    Set relayIpList = iisSmtpServer.Get("RelayIpList")
    ' Set to allow only specified ip addresses
    relayIpList.GrantByDefault = false
    relayIpList.IpGrant = "127.0.0.1"
    ' Save the settings
    iisSmtpServer.Put "RelayIpList",RelayIpList
    iisSmtpServer.SetInfo
    ' Get the smtp server domain object
    Set domainObject = GetObject("IIS://LocalHost/SMTPSVC/1/domain")
    ' Create the aliases
    Set newDomain = domainObject.Create ("IIsSmtpDomain",alias)
    
    ' Set the route action to be an ALIAS domain
    newDomain.RouteAction = 16
    newDomain.RouteActionString = alias
    ' Save the settings
    newDomain.SetInfo

    Run the script from your startup.cmd like this:

    cscript setupsmtpserver.vbs

    You can modify this script to alter all of the SMTP server features to suit your needs.

    Having done all this, don’t forget to add port 25 to your Endpoints list in csdef e.g.

     <InputEndpoint name="smtp" port="25" protocol="tcp" localPort="25" />

    So that’s it. We now have a dynamically installed SMTP server in Azure. As a word of caution, be aware that if you send large quantities of email from Azure, you may well run the risk of having the IP address blocked by anti-spam systems.

    Happy emailing 😮

     
    • SEO Grundlagen 1:46 pm on August 17, 2011 Permalink | Reply

      Thank you for this tutorial

    • kamouch 2:34 pm on September 30, 2011 Permalink | Reply

      Hi,
      How do you actualy put the startup.cmd and setupsmtpserver.vbs files on the server ?
      Thx
      Thomas

      • richardprodger 5:10 pm on September 30, 2011 Permalink | Reply

        Just add the files to your webrole or workerrole project in Visual Studio and set their build action to “content” and they will be packaged up an included.

    • Kai Nicklas 2:55 pm on October 12, 2011 Permalink | Reply

      Hi,
      According to http://msdn.microsoft.com/en-us/library/windowsazure/gg456327.aspx
      is part of the ServiceDefinition.csdef not the ServiceConfiguration.csfcg.
      In ServiceConfiguration it is an invalid child element.

    • skrim 8:27 am on February 9, 2012 Permalink | Reply

      It appears that cscript (and Azure role) crashes if any of the files is saved with UTF8 + Byte Order Mark. Setting charset to ANSI works fine.

  • Richard Prodger 1:59 pm on July 7, 2011 Permalink | Reply  

    Using RoleEnvironment in a console app in .NET4 

    If you are writing a console app in .NET4 and want to use the RoleEnvironment then you’ll get an error:

    The type initializer for ‘Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment’ threw an exception.

    To get around this, just add a “useLegacyV2RuntimeActivationPolicy” to the startup tag generated in the default app.config:

     <startup useLegacyV2RuntimeActivationPolicy=”true”>

     This is because Microsoft.WindowsAzure.ServiceRuntime.dll is a mixed mode assembly. The useLegacyV2RuntimeActivationPolicy attribute is required for referencing any mixed mode assembly, not only the Windows Azure ones.

     
  • Richard Prodger 10:18 pm on May 4, 2011 Permalink | Reply  

    WIF, ACS, STS and SSO Configuration Challenges 

    This post will be extended to cover all the issues I’ve encountered on trying to work with WIF/ACS/STS & SSO in general.

    Error #1 – Occurs on the WIF enabled ASP.NET web site after successfully logging in via ACS and any identity provider

    The data protection operation was unsuccessful. This may have been caused by not having the user profile loaded for the current thread’s user context, which may be the case when the thread is impersonating.

    • Configure IIS to load user profile. To configure IIS to load user profile follow these steps:
    • Open IIS Manager.
    • Find out what AppPool your application is using by selecting your App, right-click on it, and Select Manage Application -> Advanced Settings.
    • After that, on the top left hand side, select Applications Pools, and go ahead and select the App Pool used by your app.
    • Right-click on the App Pool, and select Advanced Settings, Go to the Process Model Section and Find the “Load User Profile” Option and set it to true.

    Error #2 – Visual Studio STS template issue

    The default template created by adding a new STS from the Federation Utility needs the line added in red below when debugging. A ThreadAbortException is thrown when the page redirects back to the calling web app. It is safe to ignore this exception.

        protected void Page_PreRender( object sender, EventArgs e )
        {
            string action = Request.QueryString[WSFederationConstants.Parameters.Action];
            try
            {
                if ( action == WSFederationConstants.Actions.SignIn )
                {
                    // Process signin request.
                    SignInRequestMessage requestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromUri( Request.Url );
                    if ( User != null && User.Identity != null && User.Identity.IsAuthenticated )
                    {
                        SecurityTokenService sts = new CustomSecurityTokenService( CustomSecurityTokenServiceConfiguration.Current );
                        SignInResponseMessage responseMessage = FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest( requestMessage, User, sts );
                        FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse( responseMessage, Response );
                    }
                    else
                    {
                        throw new UnauthorizedAccessException();
                    }
                }
                else if ( action == WSFederationConstants.Actions.SignOut )
                {
                    // Process signout request.
                    SignOutRequestMessage requestMessage = (SignOutRequestMessage)WSFederationMessage.CreateFromUri( Request.Url );
                    FederatedPassiveSecurityTokenServiceOperations.ProcessSignOutRequest( requestMessage, User, requestMessage.Reply, Response );
                }
                else
                {
                    throw new InvalidOperationException(
                        String.Format( CultureInfo.InvariantCulture,
                                       "The action '{0}' (Request.QueryString['{1}']) is unexpected. Expected actions are: '{2}' or '{3}'.",
                                       String.IsNullOrEmpty(action) ? "<EMPTY>" : action,
                                       WSFederationConstants.Parameters.Action,
                                       WSFederationConstants.Actions.SignIn,
                                       WSFederationConstants.Actions.SignOut ) );
                }
            }
            catch (System.Threading.ThreadAbortException) { } // Thrown by redirect, safe to ignore
            catch ( Exception exception )
            {
                throw new Exception( "An unexpected error occurred when processing the request. See inner exception for details.", exception );
            }
        }
     

    Error #3 – Claims aware ASP.NET site gives this error

    A potentially dangerous Request.Form value was detected from the client (wresult=”<trust:RequestSecuri…”).

    If you get this it’s because page validation is turned on by default. You can turn it off but I wouldn’t recommend that.

    The best way around this is to write a customer validation handler and insert it into the asp.net pipeline. Here is the code for the http handler.

        public class WifRequestValidator : RequestValidator
        {
            protected override bool IsValidRequestString(HttpContext context, string value, RequestValidationSource requestValidationSource, string collectionKey, out int validationFailureIndex)
            {
                validationFailureIndex = 0;
                if (requestValidationSource == RequestValidationSource.Form && collectionKey.Equals(WSFederationConstants.Parameters.Result, StringComparison.Ordinal))
                {
                    SignInResponseMessage message = WSFederationMessage.CreateFromFormPost(context.Request) as SignInResponseMessage;
                    if (message != null)
                        return true;
                }
                return base.IsValidRequestString(context, value, requestValidationSource, collectionKey, out validationFailureIndex);
            }
        }

    Here is the line to insert in the system.web section of your web.config  

    <httpRuntime requestValidationType="WifRequestValidator"/> 

    Error #4 – AppPool User Profile

    Although not directly related to this subject, my site was using the membership provider for authentication. I discovered that IIS doesn’t load the Windows user profile, but certain applications might take advantage of it anyway to store temporary data. SQL Express is an example of an application that does this. However, a user profile has to be created to store temporary data in either the profile directory or in the registry hive. The user profile for the NETWORKSERVICE account was created by the system and was always available. However, with the switch to unique Application Pool identities, no user profile is created by the system. Only the standard Application Pools (DefaultAppPool and Classic .NET AppPool) have user profiles on disk. No user profile is created if the Administrator creates a new Application Pool.

    However, if you want, you can configure IIS Application Pools to load the user profile by setting the “LoadUserProfile” attribute to “true”.

     
  • Richard Prodger 11:04 am on April 6, 2011 Permalink | Reply  

    P3P and IIS in Azure 

    I had a customer who was running a portal web site on an intranet web server that hosted a number of iframes, each one running a different web app.

    We wanted to migrate some of these apps to Azure but maintain the cookies that were being passed by the apps. In IE, iframe content is treated as third party when not on the same domain and will block all cookies by default. To get around this, you have to set a web site policy file and pass the reference to it in the headers so that the browser knows what to do.

    The following is an example of a policy file that allows cookies. This needs to be included as content in your Azure deployed web app.

    p3p.xml

    <META>
      <POLICY-REFERENCES>
        <POLICY-REF about="/w3c/example-com.p3p#policy1">
          <INCLUDE>/</INCLUDE>
          <COOKIE-INCLUDE/>
        </POLICY-REF>
      </POLICY-REFERENCES>
    </META>

    You then need to tell IIS on the Azure VM to send the custom header. You can do this in a startup task.

    Create a file call "setupiis.cmd"and add the following line, replacing the <mysite.com> with your domain name.

    appcmd set config /section:httpProtocol /+customHeaders.[name=’P3P’,value=’policyRef=""" http://<mysite.com>/P3P.xml """’]

    Please note that you must include double-quotation marks (") around a value. You must escape the quotation character by enclosing it in double-quotation marks.

    Then, add a startup task to your ServiceConfiguration.cscfg

    <Startup>
       <Task commandLine="setupiis.cmd" executionContext="elevated" taskType="simple" />
    </Startup>

     
  • Richard Prodger 6:46 pm on March 22, 2011 Permalink | Reply  

    Azure IIS7 Configuration with AppCmd 

    Got a bit stuck the other day trying to figure out how to set up authentication in IIS running in an Azure web role. I had multiple sites and wanted to have different authentication for each site. It turns out that IIS7 locks down the ability to set these in your web.config by default. Consequently, you have to run a startup task that uses the appcmd tool to modify the master configuration.

    Here is the startup task as defined in the ServiceDefinition.csdef

     

    <Startup>
       <Task commandLine="iisunlock.cmd" executionContext="elevated" taskType="simple" />
    </Startup>

     

    Here is the contents of the iisunlock.cmd

    %windir%\system32\inetsrv\APPCMD.EXE unlock config /section:windowsAuthentication
    %windir%\system32\inetsrv\APPCMD.EXE unlock config /section:anonymousAuthentication
    %windir%\system32\inetsrv\APPCMD.EXE unlock config /section:basicAuthentication

    AppCmd.exe is the single command line tool for managing IIS 7. It exposes all key server management functionality through a set of intuitive management objects that can be manipulated from the command line or from scripts.

    AppCmd enables you to easily control the server without using a graphical administration tool and to quickly automate server management tasks without writing code.

    Some of the things you can do with AppCmd:

    • Create and configure sites, apps, application pools, and virtual directories
    • Start and stop sites, and recycle application pools
    • List running worker processes, and examine currently executing requests
    • Search, manipulate, export, and import IIS and ASP.NET configuration

    AppCmd also allows server administrators to build advanced management tasks simply by combining multiple simpler AppCmd.exe commands, or reusing the output of the tool inside another program.

     
  • Richard Prodger 5:12 pm on March 10, 2011 Permalink | Reply  

    Travel Advisor – A Windows Azure DataMarket and Windows Phone 7 integration exercise 

    Over the last couple of months, I been leading a small project looking at extending the reach of the cloud to handheld devices. To test this out, we’ve built a Windows Phone 7 application that consumes data feeds from Windows Azure DataMarket, Bing, twitter and others. The app, known as “Travel Advisor”, went live on the Windows Phone 7 MarketPlace today.

    What is it?

    The application is ideal for people travelling abroad, perfect for the adventurous or regular traveller, the app provides up to the minute travel advice and warnings on every country listed by the UK Foreign and Commonwealth office. Travel Advisor provides embassy contact information, entry requirements, local customs information, local health advice, vaccination recommendations and much more.  In addition the app provides language translation services, currency conversion and local weather forecasts. Live integration with the forums of GapYear.com provides access to a community of extreme travellers and the location aware Twitter integration allows you to keep your social network up to date with your adventures.  

    How does it work?

    The UK Foreign and Commentwealth Office publishes travel advisory data as RSS feeds from their web site. We’ve created a Windows Azure worker role hosted application that monitors the RSS feeds and updates a SQL Azure database with the latest advice. The Windows Azure DataMarket then provides a discoverable interface for consuming this data in OData  format. Our Windows Phone 7 application connects to the DataMarket and retrieves the data on demand. To augment the travel advice, the phone app also consumes weather data hosted on the DataMarket by Weather Central. In addition to the the DataMarket data, the phone app makes use of Bing services for language translation and currency conversion. With twitter integration, you can use the app to tweet a location message to your feed. The app makes use of the built in GPS to automatically select the appropriate country when you are outside the UK.

    If you have a Windows Phone 7, please download the app from the MarketPlace and let us know what you think. It’s free!
    Many thanks to Dave Coplin at Microsoft for his support.
     
    • Lauren Thermopolis 5:42 pm on May 4, 2011 Permalink | Reply

      This new integration is going to be really good news for those who travel quite a lot. Not only are they carrying with them a handy translator, they are also carrying a mini map. It’s like everything a traveler needs to have all rolled into one piece of application. I mean, it has twitter integration as well! I hope to hear some more about this windows azure datamarket and windows phone 7 integration. Someday, I might get myself one of these.

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel