Azure PaaS Endpoint ACLs Part 1 - Overview
Azure PaaS endpoint ACLs were recently announced to make securing Cloud Services containing Web and Worker Roles easier; prior to this you had to use firewall rules on the Windows VMs themselves, which needed to be created using a startup task and a bit of scripting to invoke netsh
or similar. This mixing of config and code meant that if you needed to change your firewall rules, you had to change the config scripts in your source repo and re-deploy.
The management of the endpoints has now been hoisted out of the VM world and can be configured on the Cloud Service itself, so the traffic is filtered before it even reaches the VMs within. The configuration for these endpoints and their associated ACLs lives in the Cloud Services .cscfg
file which tells Azure things like which Operating System family to use, whether Remote Desktop is enabled and so on. Now, we have a new <NetworkConfiguration>
element which can describe endpoints and their associated ACLs:
<NetworkConfiguration>
<AccessControls>
<AccessControl name="MyACL">
<Rule action="permit" description="test" order="100" remoteSubnet="1.2.3.4/32" />
<Rule action="permit" description="test" order="150" remoteSubnet="123.123.123.0/28" />
<Rule action="deny" description="test" order="200" remoteSubnet="0.0.0.0/0" />
</AccessControl>
</AccessControls>
<EndpointAcls>
<EndpointAcl role="WebRole1" endPoint="Endpoint1" accessControl="MyACL" />
</EndpointAcls>
</NetworkConfiguration>
Notice that we have a few concepts that will be familiar to those who have configured enterprise routers - we have ACLs objects which can be applied to more than one endpoint, should our service have them. The ACL rules are evaluated sequentially according to their order
property, and like a regular firewall, the last rule denies all traffic from everywhere. Therefore the order matters - the first rule matching the source 'wins' and the rest are ignored. Also notice that we use CIDR notation for specifying source networks.
Separation of Code and Config
Here's the thing: the .cscfg can be thought of as logically separate from the Web/Worker role configuration within the Cloud Service - and as such this can actually be updated and deployed alone, without deploying the code too. The only part where this "code vs config" separation of concerns breaks down somewhat is that the endpoints themselves are still managed via the Cloud Service definition (.csdef
). This does make sense if you think about it - the Cloud Service is like a NAT router and firewall in the physical world, but the endpoints still live on the web servers themselves.
Your Cloud Service's .cscfg
files will still live in the same source repo that they always did, but now if you commit a change to that configuration, you don't need to re-deploy the whole app. And if you wanted to manage the configuration in a separate repo, you could probably do that too fairly easily, with some careful thought. More on that later in this series.
Updating Cloud Service config on the fly
Updating the existing in-place .cscfg
on a Cloud Service is remarkably straightforward, and if you're just updating ACL rules then this will cause your app no interruptions whatsoever. Under the hood it's probably the same process as updating a VM Cloud Service ACL via the Azure Management Portal, it's just that this hasn't been exposed to the UI yet.
You can retrieve and change the configuration via a couple of very simple PowerShell cmdlets: Get-AzureDeployment
and Set-AzureDeployment
The first of the two will give you the existing config only after drilling down to the Configuration
property, so if you want an XML object containing the current .cscfg
data you could do:
$configXML = [XML] (Get-AzureDeployment -ServiceName "myService").Configuration
The Set-AzureDeployment
cmdlet only allows you to replace the existing config by giving it a fully-formed .cscfg
file, like so:
Set-AzureDeployment -config -ServiceName "myService" -Slot Production -Configuration ".\myService.cscfg"
Next: Keeping it stable
OK, so assuming that you may have decided that you're going to manage your Cloud Service ACLs separately from the code repo, the above should give you everything you need to keep things in check. You don't want errant ACL entries from Dev/QA systems openining up your endpoints to traffic that is undesired. How can you keep that from happening, even after deployment? I'll cover that in the next couple of posts in this series.