Opening Ports on Cloud Services

There are scenarios that warrants us to open ports of the Windows Firewall. Imagine an application that coordinates work across many compute nodes. The workload coordinator needs to know and manage each compute node.

The diagram above, depicts a Virtual Machine that has direct access to instances of a Cloud Service without going through a Load Balancer. Both the Virtual Machine and Cloud Service are deployed to a Virtual Network on Microsoft Azure. Using Internal Endpoints in this scenario, would not yield the desired configuration. Endpoints are defined at the Cloud Service boundary and are IP addresses belong to the Data Center’s Network Address Space. Therefore, In order to allow the Virtual Machine to communicate over specific ports to individual Cloud Service instances, we need to use PowerShell and a Startup Task to configure the Windows Firewall.

Using PowerShell to Open a Port

$port = New-Object -ComObject HNetCfg.FWOpenPort
$port.Port = 8080
$port.Name = 'Compute Node Inbound Port'
$port.Enabled = $true

$fwMgr = New-Object -ComObject HNetCfg.FwMgr
$profile = $fwMgr.LocalPolicy.CurrentProfile
$profile.GloballyOpenPorts.Add($port)

Using a Command Line to Open a Port

REM   Add a firewall rule in a startup task.

REM   Add an inbound rule requiring security and encryption for TCP port 8080 traffic.
netsh advfirewall firewall add rule name="Require Encryption for Inbound TCP/8080" protocol=TCP dir=in localport=8080 security=authdynenc action=allow >> "%TEMP%\StartupLog.txt" 2>&1

REM   If an error occurred, return the errorlevel.
EXIT /B %errorlevel%

Configuring a Cloud Service Startup Task

Startup tasks are actions that are taken before your roles begin. Startup tasks are defined in the ServiceDefinition.csdef file by using the Task element within the Startup element. Frequently startup tasks are batch files, but they can also be console applications, or batch files that start PowerShell scripts.

We have two options to open Ports on the Windows Firewall. For this post, I will use PowerShell because it has more steps. This example can be used as a starting point to run other PowerShell scripts from Startup Tasks.

Cloud Service – ServiceDefinition.csdef

The Startup Task is defined on a per role basis. In our case, we must elevate the execution context so that we may interact with the Windows Firewall.

<?xml version="1.0" encoding="utf-16"?>
<ServiceDefinition xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="ComputeService" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
	<WorkerRole name="Compute" vmsize="Standard_D1">
		<Startup>
			<Task commandLine=".\startup.cmd &gt; startup_log.txt" executionContext="elevated" />
		</Startup>
		<Runtime executionContext="elevated">
			<EntryPoint>
				<ProgramEntryPoint commandLine="worker.cmd" setReadyOnProcessStart="true" />
			</EntryPoint>
		</Runtime>
	</WorkerRole>
</ServiceDefinition>

Command Line – startup.cmd

This command file elevates the execution policy for PowerShell, then it executes the startup.ps1 file. It’s important to note that every time the command line is executed, it produces a StartupLog file, which helps to confirm that everything ran as expected. If an error occurs, this log file can save you countless hours of debugging by providing insights about what may have gone wrong.

REM   Attempt to set the execution policy by using PowerShell version 2.0 syntax.
PowerShell -Version 2.0 -ExecutionPolicy Unrestricted .\startup.ps1 >> "%TEMP%\StartupLog.txt" 2>&1

IF %ERRORLEVEL% EQU -393216 (
   REM   PowerShell version 2.0 isn't available. Set the execution policy by using the PowerShell version 1.0 calling method.

   PowerShell -Command "Set-ExecutionPolicy Unrestricted" >> "%TEMP%\StartupLog.txt" 2>&1
   PowerShell .\startup.ps1 >> "%TEMP%\StartupLog.txt" 2>&1
)

REM   If an error occurred, return the errorlevel.
EXIT /B %errorlevel%

echo SUCCESS
exit /b 0

PowerShell – startup.ps1

This file contains the PowerShell script listed above. This is also the place where we can configure other aspects of out Cloud Service via PowerShell.

$port = New-Object -ComObject HNetCfg.FWOpenPort
$port.Port = 8080
$port.Name = 'Compute Node Inbound Port'
$port.Enabled = $true

$fwMgr = New-Object -ComObject HNetCfg.FwMgr
$profile = $fwMgr.LocalPolicy.CurrentProfile
$profile.GloballyOpenPorts.Add($port)

Packaging

For this to work, we need to place the Command Line and PowerShell files at the root of the Cloud Service Role. If you are using Visual Studio to create your package, be sure to set both files to Copy Always otherwise they will be missing from the resulting package. If you are using PowerShell to create the package, the CmdLet will take everything from the role’s directory.

Deploying the Cloud Service

There is nothing different about deploying a Cloud Service that has Startup Tasks. Using your tool of preference, create a new Cloud Service package and deploy it to Microsoft Azure.

Using PowerShell to package the Cloud Service requires you to navigate to the Cloud Service directory and execute the Save-AzureServiceProjectPackage command. This will produce a cloud_package.cspkg package file.

To deploy Azure Cloud Services, I usually use PowerShell. This is an example of what you may write yourself.

New-AzureDeployment `
                -Package 'C:\\cloud_package.cspkg' `
                -Configuration 'C:\\ServiceConfiguration.Cloud.cscfg' `
                -Slot Production `
                -Label 'Compute-2015-02-17' `
                -ServiceName  'DemoCloudService' `
                -Name 'DemoCloudService' `
                -Verbose

Resources

No Comments

Be the first to start the conversation!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.