Thursday 29 March 2012

URL Rewrite module in IIS 7 with shared config

We've waited a long time for a relatively simple URL Rewrite module in IIS.  It's not news that we've now got it, in IIS 7 onwards, but it's not baked in as standard (unlike most distributions of Apache where mod_rewrite is most likely the first module on the list).

You can download URL Rewrite from here (x64): http://go.microsoft.com/?linkid=9722532 or here (x86): http://go.microsoft.com/?linkid=9722533 and there's plenty of documentation here: http://www.iis.net/download/urlrewrite

One area that causes a bit of difficulty though is when Shared Configuration comes into play.  Shared Configuration is a handy little facility built into IIS that lets you maintain one configuration across multiple IIS servers - so it's great for a web farm setup.

What's not so great is that it doesn't play nice with the URL Rewrite module.  So having been through the pain of getting the two working together, I thought I'd write it all down, so you don't have to.

So I'm assuming you already have your shared config up and running, everything is fine and dandy, but (like me) you've just got an SSL certificate and you now want to force all HTTP traffic to HTTPS. This is what we do:

  1. Disable shared config on both nodes.  This is at the server level:

    Shared configuration - it's at the server level, not the site

    Untick the check box, and hit 'Apply'.  You'll see a scary-looking dialog box:

    Looks scary, but it's only asking whether you'd like to hold on to the config you know works, or swap it for something ancient that probably doesn't.  The right answer is 'Yes'.

    The question here is 'do you want to overwrite your local config with the shared config to keep things working the same as when they were shared'? 'Yes' is the answer here - you simply don't know what's in that local config directory so you'll want to overwrite it with what you do know.

    Don't worry, we're not restarting IIS, just the Manager.  Oh, and the Management Service.

    Close and re-open IIS Manager.  At the server level, find 'Management Service' - it's at the bottom of the page, under 'Management'.  Right-click and select 'Restart'.

    That's the Management Service. That's at the server level too.

    Now repeat on the other nodes that share the same config!

    Check that your site still works - load balancing and DFS should still be working just the same, but remember that the IIS configurations are now managed separately, down in the bowels of C:\Windows\system32\inetsrv.
  2. MAKE SURE NO OTHER CONFIG CHANGES HAPPEN!!

    Now you can't rely on IIS to keep the config the same between the servers, so you need to be very careful not to introduce any un-controlled differences between your configs. Tread very carefully...
  3. Install the URL Rewrite module on both nodes, and make sure it's working.

    The module comes as a standalone installer, so it should just be a case of clicking through the wizard and letting it do its thing.

    Close and re-open the IIS Manager, and you should see the URL Rewrite module available under 'IIS' at the site level.

    Success! URL Rewrite is alive! At the site level...

    Check this is available on each node in the web farm.
  4. Re-create the shared configration

    Firstly, we need to export the local configuration on one of our servers to use that as the new shared config. At the server level, go to 'Shared Configuration' and firstly select 'Export Configuration' (it's over on the right).

    Select the 'physical path' as the original shared config location (that's right, we're going to overwrite the old shared config with the local config from this server!).  Choose an encryption password - make a note of it as you'll need it for every node you do this on.

    Now, tick the 'Enable shared configuration' box and choose the physical path that you just saved the config to.  Don't worry about user name or password.

    Apply this change (again, it's over on the right) and you'll have to enter the encryption password, and restart IIS Manager (and management service) again.
  5. DON'T BE SCARED!!!!

    You might find that this momentarily generates some 503's (Service Unavailable) on your site - don't worry, it's momentary and everything should be up and running again very quickly.
  6. You should now have a shared config running URL Rewrite.
  7. Add your rules into the 'URL Rewrite' section against the site config in IIS.

    You can add this into your web.config file (there will probably already be some stuff in the <system.webServer> area)

    <system.webServer>
            <rewrite>
                <rules>
                    <rule name="Force HTTP to HTTPS" stopProcessing="true">
                        <match url="(.*)" />
                        <conditions>
                            <add input="{HTTPS}" pattern="off" />
                        </conditions>
                        <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Found" />
                    </rule>
                </rules>
            </rewrite>
    </system.webServer>


    Or, if you prefer the GUI, your rules should look like this:

    The rewrite rules. At the site level.

    And the rule detail looks like this:

    The detail.

  8. Remember, the shared config ensures that your changes get propagated throughout your web farm, so that should be that, your site should now successfuly rewrite all HTTP requests seamlessly to HTTPS.
At least, that's the theory.  I completed this successfully on a pair of fresh VMs today, I'll update when I've done it for real on our boxes that have been in production for months...

The security database on the server does not have a computer account for this workstation trust relationship

I needed to test some IIS shared config changes; I knew I'd break our live environment so I needed to set up a couple of VMs to simulate the two physical machines we have.

Building VMs is always a pain; well, the initial build is pretty easy, but once the machine's up and running, getting all the patching done is a right chore...especially when you've never been able to successfully install the MSDN Windows 2008R2 SP1 ISO... (but that's another story)

So I thought, "aha! I'll get one machine set up, then it'll be a simple matter of using the clever 'Export' feature in Hyper-V and I can quickly duplicate my machine, rename it, and off we go!"

So I did just that, the export and import worked fine (once I realised I needed to wait for the export to complete before trying to start the import), and pretty soon, I had two identical VMs, all nicely patched up.

I fired up the new machine first, so that I could change its IP address and rename it (we don't want IP/domain name conflicts, do we?) and that was all fine and dandy.  I started up the original VM, logged in and saw:

'The security database on the server does not have a computer account for this workstation trust relationship.'

Wait...what?

This is the original machine though, surely if any machine should have an issue, it'd be the new one, wouldn't it? I searched the web and didn't find a great deal of useful help, stuff about cross-domain trusts and hacking AD to make things work.

In the spirit of 'try switching it off and back on again first' I thought that maybe the new VM had taken on the computer account in AD, and retained it even with its new name.  The solution might be to just take the original VM out of the domain and add it back in.

And sure enough it was.  So if you're duplicating VMs within a domain (I suppose the same applies for ghosting physical machines too) make sure you either a) add the machines to the domain after they've been duplicated, or b) if the original machine is already in the domain, remember that whichever one you start up first will take the machine account in AD, and all the others will need individually adding back into the domain so they can get their own machine accounts.

Wednesday 8 February 2012

Enable Service Broker in SQL Server painlessly

Every so often, I find myself having to create a new testing, staging, whatever non-live environment for an application.  Often I forget that Service Broker needs to be enabled at the database level before it can be used - a database restore doesn't do this.

So often I'm hunting around for a code snippet to enable the Service Broker on a database that's already running (as usually it's the task I've forgotten to do earlier!)

Here's the code snippet:


ALTER DATABASE Titan_Reporting SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE Titan_Reporting SET ENABLE_BROKER
GO
ALTER DATABASE Titan_Reporting SET MULTI_USER
GO

Don't forget the 'WITH ROLLBACK IMMEDIATE', otherwise you'll be waiting a looooong time for the first statement to complete! 

Monday 6 February 2012

My new blog

I have a new blog.  It's a place where I write stuff.  It's called 'Data and that.', for want of a better title.  I plan to write lots of informative and insightful stuff about data, its security, working with it, and what advances in data may mean for society in the future.  Hopefully it will stay generally on topic, but I won't guarantee any such thing.  Maybe you'll enjoy reading it, maybe you won't.  You don't have to.

So far this is the only entry.  How many other well-intentioned, single-post blogs are out there, I wonder?  I know I have one or two out there in the cyber-wasteland.  But I have other posts lined up for this one.  I just need to get something posted to start things moving, so this is it.

Here goes...(deep breath)

<PRESSES THE BIG ORANGE BUTTON MARKED 'PUBLISH'>