Learn about Windows PowerShell
Summary: Windows networking engineer, James Kehr, discusses using Windows Azure cmdlets to create endpoint ACLs.
Microsoft Scripting Guy, Ed Wilson, is here. This weekend we have a two-part series from guest blogger, James Kehr. It is really cool. Take it away, James…
Greetings my fellow netizens. James Kehr here with the Windows Networking Escalation Support team to discuss Windows Azure and how you can use the Windows Azure cmdlets to create endpoints and endpoint access control lists (ACLs). Before diving into the commands, I think it best that I take a little time to explain Windows Azure networking basics, including a quick primer about exactly what an ACL is. If you are familiar with these details feel free to skip a bit.
When I say basics, I really mean “the basics.” A deep dive into how networking in Windows Azure works would take far too long, so I shall summarize—and that will still take some time. So let’s begin…
Every organization within Windows Azure lives in their own little networking world called a virtual network (VNET). Each of these VNETs are isolated to the point where they cannot intrude into another organization’s VNET. Add a little networking wizardry, and this gives Microsoft the ability to securely host several thousand organizations that are simultaneously sharing the same three private IPv4 address spaces within the same data center. Servers and services within a VNET can only be accessed in three ways:
From a network security perspective, the first two options are not very bothersome. Your servers and services are supposed to talk to each other, after all. If they are not supposed to, you can stick them in separate VNETs and they will no longer be able to. Likewise, the gateway part is not worrisome because site-to-site and point-to-site Windows Azure gateways (VPNs) use data encryption and integrity methods to ensure that no one can snoop on or modify your data in-flight. It is the public endpoint part that worries the people who worry about network security. Why? By default your public endpoints are just that. Public. To the entire Internet. Which is good or bad—depending on what your cloud service is used for.
This brings us to the main point of this blog post: ACLs.
Access control lists are not new, nor are they unique to Windows Azure. They are a very common networking method that is employed by networking security types to limit access to a network endpoint. Think file permissions for networking.
The ACL itself is a set of ordered rules that are applied to a networking endpoint. Each rule generally consists of a rule order number, a subnet, and one of two actions: permit or deny. Please be aware that subnets in Windows Azure are defined by using CIDR notation. When a network frame arrives at an endpoint with an ACL, the network device will process the frame against the rules, in order, and decide whether to permit or deny the traffic. When denied, the traffic is blocked. When permitted, the traffic is passed on to the destination. When a rule match is found, ACL processing stops.
The endpoints in Windows Azure are virtual, but ACLs still apply. When you create a cloud service, such as a virtual machine, the service is given a public IP address, a private IP address, and one or two endpoints. Each endpoint has a public and a local side that are connected together. This is called an endpoint map. The public side is exposed to the Internet, and by default, it is completely open. The local side is the TCP or UDP port that your server or service will be listening on.
For example, when a virtual machine is created in Windows Server, a Remote Desktop Protocol (RDP) endpoint is added. A public port of 60000 may be opened on the public IP with a corresponding local port of 3389 opened on the private IP. If you try to connect to the server from the Internet by using port 3389, the connection will fail. When you connect to the public IP on port 60000, the traffic will be forward to port 3389 on the private IP address, which is bound to the virtual machine and allows you to connect a remote desktop session from the Internet.
Pop quiz time! If you want to connect to an Windows Azure virtual machine through a Windows Azure gateway or from a different server on the same VNET, what port should you use? Answer: 3389.
In both scenarios you are bypassing the public endpoint, and you do not need to worry about endpoint mappings or ACLs. The one exception is if you use the public name for the server (for example, service.cloudapp.net), which would take you through the public endpoint. Depending on routing…
I’ll stop there. You get the idea.
I think this is enough of a Windows Azure networking primer, so let’s move along to the Windows PowerShell parts, shall we?
As of this writing, you need Windows PowerShell to create endpoint ACLs in Windows Azure. More specifically, you need the Windows Azure module for Windows PowerShell. This feature may show up in the management portal very soon, maybe even by the time you read this, but this is still good information to have for automation and general Windows Azure cmdlet knowledge. For information about how to download the Windows Azure module for Windows PowerShell and how to set it up, see Get Started with Windows Azure Cmdlets.
After setup, you can add an endpoint and an ACL by using Windows PowerShell. For our examples today, you can imagine the following scenario…
You are setting up a web server, Web01, in Windows Azure for an Intranet site. The only IPs you want to access the website are the app server, App01 (184.108.40.206), and the corporate proxy servers. The proxy servers will be on an inaccurate subnet, because they cannot route across the IP address range of 172.16.0.0/39.
The script looks like this:
# create an endpoint for HTTP
Get-AzureVM -ServiceName Web01 | Add-AzureEndpoint -Name "HTTP" -Protocol tcp -PublicPort 80 -LocalPort 80 | Update-AzureVM
# create a new ACL
$acl = New-AzureAclConfig
# add some rules to the ACL
Set-AzureAclConfig -AddRule -ACL $acl -Order 0 -Action Permit -RemoteSubnet "220.127.116.11/32" -Description "Allow App01"
Set-AzureAclConfig -AddRule -ACL $acl -Order 1 -Action Permit -RemoteSubnet "172.16.0.0/29" -Description "Allow corp proxies"
Set-AzureAclConfig -AddRule -ACL $acl -Order 2 -Action Deny -RemoteSubnet "0.0.0.0/0" -Description "DenyAll"
# apply the ACL to the HTTP endpoint
Get-AzureVM -ServiceName Web01 | `
Set-AzureEndpoint -ACL $acl -Name "HTTP" -Protocol TCP -PublicPort 80 -LocalPort 80 |`
Let’s break down how this works. The first thing you may notice is that I am getting the AzureVM object and passing that through the pipeline:
Get-AzureVM -ServiceName Web01 | …
Why would I do this when there is a -VM parameter for Add-AzuerEndpoint? Because older versions of Windows Azure cmdlets don’t work when you store the VM object in a variable and then pass the variable to the parameter. This issue was fixed in the August 2013 release, but rather than tell everyone to upgrade I wrote the post by using the most compatible code possible.
The second thing you may notice is that I used ServiceName and not the virtual machine name. When dealing with endpoints and ACLs this is the preferred way to do it because of the way load-balanced endpoints work. It’s a good habit to get into so I use this method exclusively. I’ll cover a bit more of the why in Part 2. The ServiceName is usually the same as the virtual machine name. The Cloud Services section of the management portal has the list of all the service names and the associated virtual machines and services on the Instances tab, in case you don’t know. You can also use Get-AzureVM to grab the list.
… Add-AzureEndpoint -Name "HTTP" -Protocol tcp -PublicPort 80 -LocalPort 80 | …
This cmdlet accepts the Windows Azure VM object from the pipeline and adds the endpoint to all the virtual machines in the service. If you only want the endpoint added to a single virtual machine in a service, add the -name <vm name> parameter to the Get-AzureVM cmdlet.
We give this endpoint a name, protocol, public port, and local port. This is the minimum you need to define the endpoint. You can add the ACL when you create the endpoint, but for demonstration purposes, I will not do this.
When editing endpoints, ACLs, and other Windows Azure VM objects, they do not get committed until you run Update-AzureVM. And that’s really all that needs to be said.
The next step is the ACL creation. The best way to do this is to create a blank ACL and then add rules. The blank ACL is created with this command:
Then the rules are added to the ACL with Set-AzureAclConfig:
ACL rules are processed in order, starting with rule 0. When there is a rule match, the remaining rules are ignored. So when IP 18.104.22.168 connects to this endpoint, only a single rule is processed, and access is permitted. When 22.214.171.124 tries to connect, all three rules are processed, and access is denied.
This is important to remember when planning your ACL rules. Where you put deny and permit rules can greatly affect endpoint access and performance. Speaking of performance, keep the number of rules to a minimum because large rule lists can be performance impacting.
Windows Azure ACL rules need an order, an action, a subnet, and the ACL that the rule belongs to. The order number may appear optional, but it is not. When no order is provided, the Rule IDs are given incremental numbers, but the orders are all zero. When you subsequently try to add the ACL to the endpoint, you get a nasty red error back from Windows Azure. So add those order numbers.
The description is how the rule shows up in the Get-AzureAclConfig and Get-AzureEndpoint cmdlets. I recommend keeping those short.
The first rule contains a very interesting subnet mask: /32 (255.255.255.255). This is how you add a single IP address, for example, the IP address of App01:
The second rule adds the organization’s proxy server subnet. Here, the /29 (255.255.255.248) subnet mask is used to show how a range of IPs are added:
Finally, we block everything else. 0.0.0.0/0 covers the entire IPv4 address range. Because ACL rules are processed in order, I do not need to worry about the proxies or App01 getting denied because the DenyAll rule will never be processed when those systems connect to the endpoint.
The final step in our script is to add the ACL to the endpoint and commit the changes. Again, I get the Windows Azure virtual machine by service name, pass that to the pipeline where the Set-AzureEndpoint cmdlet applies the ACL to the endpoint, and the Update-AzureVM cmdlet commits the changes.
With these rules in place, no one can access my website unless they have VPN access, use my corporate proxy servers, or are signed in to App01 via RDP. That makes this a pretty secure endpoint.
That’s it for Part 1. Tune in tomorrow for Part 2, where I will discuss removing rules, changing rules, and load-balanced endpoint.
Thank you, James! I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at firstname.lastname@example.org, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy
Is there a way to create Windows Azure co-administrator using Powershell?
How do I create a new Windows Azure subscription using powershell?