Wednesday, 13 February 2013

Azure Platform as a Service vs Infrastructure as a Service

Platform as a service (paas) sounds nice, you have a load of servers on the cloud somewhere where you are paying just for what you need or use and these are quickly scalable up and down. In the case of Azure, this means you get an automatic web farm with multiple instances and this is a real headache taken away for highly scalable applications. So I want to describe my experiences of Azure platform as a service against any other infrastructure as a service (iaas). I haven't used Azure iaas but I'm guessing it similar to Amazon etc.

Advantages of Azure

As you might imagine, Azure has been designed to be easy-to-use, otherwise paas wouldn't be worth it. The web management interface is quite slick and the ability to deploy directly from Visual studio is very helpful. You can deploy databases either directly from a database project in Visual studio or directly from SQL Server Management studio. There are various monitoring options as expected and I haven't spent much time here yet. There is also the ability to extend the functionality of Azure instances using startup scripts, commonly using powershell, which can allow you to do pretty much everything you would expect on the underlying server.

Problems with Azure

I think it would be fair to say that the initial setup and deployment of a basic application is quite straight-forward but the deployment process can be very slow, especially when compared to my old manual deployment via subversion. This is annoying when a small mistake breaks something and you have to "roll back". My deployment usually takes about 10 minutes, this is even when using "deployment update" rather than "deployment replace".
Since the infrastructure is deliberately hidden, there is the trade-off between needing to access it for debugging purposes and trying to keep people away from fiddling with it. You can enable remote desktop access on the deployment but I have found this troublesome and error prone and not at all easy to debug.
Since the platform is effectively a large eco-system which Microsoft own, if you want to debug locally, you have to use their emulator on your own PC to debug. Again, I have found this error prone and it can throw fatal errors without much clue as to what has happened. It also means you cannot always run the application directly from IIS if the Azure emulator isn't working (I get errors in the azure system somehow) and therefore you have to deploy to test things. It also means that you are not running code and writing files to the kinds of places you think since the debugging (and deploying) process packages the files up and moves them away from the project folder. This means that file changes aren't usually picked up when debugging and you have to restart the debugger (if it works!).
There are problems with using things like diagnostics, something that is quite fundamental to setting up new systems with all their inherent problems. This was related (I think) partly to a major change that occurred in the Azure SDK which majorly re-factored namespaces but without renaming the classes leading to confusion as to which online examples related to which versions of the SDK but I also, I think, many of the online samples didn't work for multi-instance web services which meant I spent a long time trying to get something to work. I had almost nothing to go on (except knowing it didn't work!) and eventually stumbled on an example which was different and which then worked for me.

Conclusion

There are always teething problems with new systems and many of the things I have stumbled on I will not have to stumble on again so we dream of it all just starting to work and being happy. The issue it did raise, however, was that although Microsoft have massively tidied up the MSDN style help articles for Azure, documentation is still a little fraught. It either doesn't include enough details about its applicability or include any help when the suggested code doesn't even work. Of course, as soon as you live azure, there are a plethora of other examples and opinions, many of which are between poor and useless. I think an Azure wiki might make these kinds of things a bit easier but I am now looking forwards to getting the diagnostics into shape!

Monday, 11 February 2013

Cannot find file named 'approot\bin\startup.cmd' for startup task

Another pain. If you are trying to create a startup command file for Azure to run when starting up new instances, you might find the error as above. In my case this was because when copying MyFolder/startup.cmd to the output directory, Visual Studio was also copying the parent directory and the file ended up being at approot\bin\MyFolder\startup. Rather than changing the path of the startup script specified in the csdef, I just moved the command file up to the application level and deleted the directory.

The SSL settings for the service 'SslRequireCert' does not match those of the IIS 'None'

I don't know how Microsoft manage to do this but they create error messages which sound impossible to understand until you understand them and then they make perfect sense!
Anyway, this is (for me) an Azure message after attempting to connect to a WCF service which has client certificate TLS enabled. What it is simply saying is that the service requires a client certificate but IIS (which is serving the site from Azure) has not been configured to require a client certificate.

There are a couple of steps to fix this on Azure (a similar process is required for IIS but I will focus on Azure).

  1. I will not describe any certification process but obviously you will need to set up certificates at both the service side (so the service can verify the client) and also at the client side. In Azure this generally consists of adding the relevant certificates to both the Azure portal (by uploading the relevant certificate) and in the project itself by adding the certificate(s) to the certificates list in the relevant web role.
  2. You will need to unlock the relevant application host section to permit the web config to include the client certificate requirement. You can do this by creating a startup batch file in your web project (make sure you save it as ASCII rather than Unicode apparently) and then ensure this is copied to the output directory in properties (I called mine startup.cmd). Then add this batch file to a startup task in the csdef file. I had to do this in the XML file rather than the gui. 
  3. The code inside the startup.cmd file should be %windir%\System32\inetsrv\appcmd.exe unlock config /section:system.webServer/security/access
  4. The code inside the csdef file to get this to run (inserted between <webrole> and <sites>) was
    <Startup>
          <Task commandLine="startup.cmd" executionContext="elevated" taskType="simple"></Task>
    </Startup>
  5. This code will allow you to add the following under system.webserver in your web.config:
  6. <security>
        <access sslFlags="Ssl, SslNegotiateCert" />
    </security>
    
  7. In my case, I do not want to insist on a client certificate for all connections, which is why I put sslnegotiatecert rather than sslrequirecert but you might put something else in here. I also always require ssl for the service but this is kind of taken care of under Azure by only creating an ssl endpoint.
  8. I think there are various ways of controlling client certificates. I think by default the service will accept any client certificate that is trusted (including its parent certificates) on the server/azure portal. Otherwise, you can specify exactly which certificates to require to provide more fine control of who can and can't connect.
  9. If you try and connect to the service in the browser, you should be prompted with a "choose certificate" dialog otherwise your client app can set this up in configuration or in code.