Read up on part 1 of securing workloads to get the background on the introduction of the WAF component. This post will be heavy on the why again. The how's are coming, I promise!
The situation is the same, we're looking to secure this deployment:
We have already introduced the WAF in the previous post. Enter the next step: locking down the network.
One of the main asks of compliance and security policies, is to segment your networks and have workloads in one of those segments. The typical setup from many moons ago was that none of your servers were accessible unless you were on the company network. Nothing was accessible from the outside, unless it passed the firewall, reverse proxy, load balancer, jump box host etc.
In terms of security and compliance stance in the cloud, the mindset has not changed. Security in-depth and zero trust environments, require you to secure both the identity landscape (RBAC roles in azure) and the network perimeter (how connections and data flows in your azure environment). A design to answer those security requirements:
What’s shown here are 3 subscriptions, each with their own VNET in it. There is a management VNET (VWAN-VNET) that takes care of all routing, security etc. The other VNET’s are then connected to that management VNET, and all or only a subset of traffic passes through/from that management VNET.
There are many variations to this image, they are outside the scope of this post. I’ll ask Chris to write up some posts about the many options in the land of network control. It’s a broad and interesting topic.
In any case, what does that mean for us? If we go back to our earlier design of the WAF + app service.
We must first consider that our app service is not in the network, nor is our database. Even if the app gateway is in between the public web and our app service, there is still a DNS record (like https://myappservice.azurewebsites.net) that points to the app service, and public access is still open on the app service itself. Visually, this is the reality at this point:
The first thing you will want to do is stop the traffic going directly to the app service, so that the WAF can do its job. Shielding the app service from outside requests can be done by using a private endpoint on the app service.
What Azure Private Endpoint + Azure App Services achieve, is the full isolation of the app service, according to the docs.
From the docs:
From a design perspective, what we’ve done is this:
We’ve brought the app service into the network and shielded it from outside access. We have now successfully secured the app service with a WAF. Now, the side effect is that the AppGw and the app service are on the network, and now we can let the IT management team secure outgoing traffic if they choose to. To get incoming traffic secured by the management network as well, we would need to do some more configuration changes. That is possible, but I feel that is out of the scope of this article. I hope by now the idea is clear.
At this point, we’ve made big steps towards being compliant with networking requirements.
We’ll have to do the same for the other resources and then the final design becomes something in the lines of:
One of the intended side effects we now have, is that the app service is not accessible anymore through the public network. If we enable the private endpoint and configure the firewall on the SQL server and key vault as well, the same will happen for those services: not accessible from the public environment anymore. In terms of network security and compliance, this is a big step towards security-in-depth. This goes beyond identity security and expands towards network security. What's not to like?
The problem: deployments
Let’s consider the use of a CI/CD tool for a minute, like Azure DevOps. ADO has 2 options for build servers: Microsoft hosted build servers, and self-hosted. Microsoft’s version is running in the cloud, not your network. Well, that basically means those servers won’t be able to access the app services anymore.
If we want to be able to deploy to the app service, we need to resort to hosting our own ADO build servers. The full setup could then become something in the lines of the following design:
Now, because you wanted to be more secure in azure, you have the added burden of managing your own ADO build agents. Either through docker or through VM’s. Depending on the size of your organization and what technology choices your teams have, this could become a big task. Imagine having to maintain java, python, ruby, .net framework, net core, powershell, bash, … toolings on a VM, just because you want your azure services to be more secure. Luckily, the ADO team publishes the code they use to build their VM’s. We can re-use their work to help minimize ours.
If all this is of interest to you, stay tuned. I’ll be walking you through setting things up in azure for both the development aspect, as well as the DevOps engineer aspect.