Tuesday 25 February 2014

Enabling HTTPS in Azure via worker InstanceInput endpoints

Wow, what a rare and specific thing you might want to do - but we certainly did, and since there was nothing I could find in the Google Brain, I had to figure it out for myself...

In a nutshell, here's how to do it:



  1. Create the endpoint via the role properties in your cloud service project. Since https is not an option, we need to select tcp:

    Also don't be deterred by the fact you can't select an SSL certificate here.
  2. Upload your SSL certificate to your cloud service via the Azure portal, and also make it available via the Certificates tab in your role properties:


  3. Now here's the trick, you need to bind the certificate to the internal port of the role (in this example, 10100). You can do this by running the netsh command as a startup task for the role.

    Create a batch file called bindcertificate.cmd in the root of your worker project. Ensure the file properties are Copy To Output Directory: Copy always.

    Add the following content to the file:

    @echo off

    REM   *** Bind the SSL certificate to the internal input endpoint (appid is irrelevant) ***

    netsh http add sslcert ipport=0.0.0.0:10100 certhash=4F66816E3856A3816246D17A77C62E4C66E641AF appid={00112233-4455-6677-8899-AABBCCDDEEFF} >> "%TEMP%\StartupLog.txt"

    REM   *** Exit batch file. ***

    EXIT /b 0

    Replace the port number with your private port, and the certhash with the thumbprint of your SSL certificate.
  4. Finally, add the batch file as an elevated startup task in your ServiceDefinition.csdef:

    <Startup> <Task commandLine="startuptasks.cmd" executionContext="elevated" taskType="simple" /> </Startup>
  5. In terms of setup, that's it. Now assuming you're using WCF to expose endpoints via the worker role, you can now create a binding with Transport security, e.g.:

    var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Search"].IPEndpoint.ToString();

    var host = new ServiceHost(yourImplementationHere);

    var binding = new WebHttpBinding(WebHttpSecurityMode.Transport);

    var ep = host.AddServiceEndpoint(
        typeof(IYourImplementation),
        binding,
        string.Format("https://{0}/YourEndpoint", endpoint));

    ep.Behaviors.Add(new WebHttpBehavior());

    host.Open();
You should now be able to access your endpoint externally, using your Azure DNS entry, along with the relevant external port, e.g.:

https://yourcloudservice.cloudapp.net:10106/yourendpoint  (role instance1)
https://yourcloudservice.cloudapp.net:10107/yourendpoint  (role instance 2)

Anthony.

No comments: