Using Application Roles for authentication in Your Services

A couple of days ago a friend asked me the question ‘How should I authenticate services with each other using roles’. I wanted to point him to a post I wrote last year, ‘Using an Azure Managed Identity to authenticate on a different App Service’, but I noticed this post wasn’t as complete as I remembered it to be.

While it does explain how to enable authentication in your service and using a Managed Identity for this, it doesn’t cover how to add roles in your application and assign them to a user or service principal (like a Managed Identity). So, let me cover the missing parts for the role-based authentication over here.

Adding roles to your App Registration

Wouldn’t it be nice if there was a possibility to add roles to your App Registration via the UI?
Well, that doesn’t exist.

You have to add your application roles in the manifest of the application, which is a big piece of JSON. I’m going to assume you have created an App Registration, as mentioned in the linked post above, and can navigate to the ‘Manifest’ blade of this application.
Over there you’ll see a property called appRoles.
Manifest with appRoles inside

As you can see in the image above, I’ve defined a role over there with a description Reader Role, meant for reading access in the application. For reference sake, here’s the JSON:

Read more →

Developing in an Azure Virtual Machine

I’ve been creating solutions for customers on my development laptop for years now. This works great as it’s a portable device and we get to have some great hardware in a compact form nowadays. However, laptops are still quite slow when you compare them to a desktop. This has become quite noticeable to me as I’ve been doing more development on my new desktop.
You can get some nice laptops with desktop-like performance, but most of the time it’ll cost a lot of money and will add a couple of pounds in weight. As I like to travel light, when travel is allowed again, a heavy laptop isn’t ideal.

Seeing there’s lots of horsepower in the cloud, it occurred to me I can just as well spin up a beefy virtual machine in Azure and develop on there. The main downside to this scenario is you need a (stable) internet connection to do any development. But to be honest, I need an internet connection anyways to do some actual development.
I do need this virtual machine to be safe and secure, so spinning up a VM and connecting to it via a public IP through RDP isn’t advised. To protect a virtual machine from the big bad internet you can add it in a virtual network and connect to it via a private IP-address. Of course, this makes the initial deployment a bit complex.

Read more →

Securing Your App Service with a Vnet

My last post was on integrating your Azure App Service with a virtual network (VNet). This post is the other way around. It’s on how to put your App Service in a VNet, or rather, behind a VNet.
If you want to put your Azure App Service inside a VNet, you’ll have to look for the App Service Environment (ASE). This is an offering of dedicated machines that are placed inside a VNet and you’re paying a rather hefty fee for this. While I like the concept, I think it’s quite expensive for most scenarios. Sure, an ASE has its uses, but most customers and projects I’ve come across don’t need it for the current price.

There is one thing that most customers DO want, protecting their services from the outside world. The public cloud, like Azure, is a PUBLIC cloud. By default, anyone can access your services.
Lucky for us, most Azure services have rather decent protection and can also be integrated into a virtual network, though some need an additional price/service tier to make it possible. The same goes for Azure App Services. For quite some time now it is possible to add an access restriction that only allows traffic from a specific virtual network (VNet).

Read more →

Vnet Integration for Your App Service

It’s always a good idea to secure the resources in your Azure subscriptions. One way to do this is by using virtual networks. In a lot of cases, you will put SQL Azure servers, storage accounts and, other services in a virtual network. This will make sure the services can’t be accessed from the public internet unless you explicitly say so.
There are many more advantages to putting services in a virtual network, which I won’t be covering in this post.
This post is on how to integrate an App Service to a virtual network.

The different VNet integration types

At this time, there are 2 types of VNet integration for App Services. They are called ‘Regional VNet Integration’ and ‘Gateway-required VNet Integration

If you’re running a relatively simple setup, located in a single region, and don’t require a fancy networking setup, it’s probably a good idea to go with the Regional VNet Integration. This one is rather easy to set up and manage.
With this VNet integration, you can still use NSGs (Network Security Groups), route tables, private endpoints, ExpressRoute, and connect to resources in the same region you’re app is located in.

If there’s a need to connect to one or more VNets in another region, the Gateway-required VNet Integration is the way to go. With this integration your service plan can connect to multiple VNets (each app can only connect to a single one), you can manage your DNS and get to create a point-to-site VPN between the different VNets. This is a bit overkill for most scenarios I’m seeing, but if you’re at a large customer or going global, it makes sense to go with this option.

Read more →

Deploying Azure Functions on a Linux Service Plan

Some time ago, about 7 months, I had to build a service that creates a PDF document from HTML. The library of choice was IronPDF. Creating PDF documents with this library is a breeze, but we stumbled across a small issue.

The HTML-to-PDF-converter-service is hosted inside an Azure Function, for reasons. We noticed creating the documents took quite a lot of time. After inspecting the allocated instances we discovered both the CPU and Memory were constantly spiking to maximum capacity. That’s not good.
What made things worse, the generation sometimes took up to 37 minutes to complete! That’s not acceptable if your customers are waiting for the document.

This service was deployed on Windows instances, as it’s the default.
Because Linux is more lightweight compared to Windows, we started doing a test if the document rendering would be faster on Azure Functions hosted on Linux instances. The results were staggering!
On the Linux instances, all of the documents being generated never took more than 3 minutes to complete (99th percentile) and the used resources were less. We were still using a lot of CPU and memory, but acceptable levels. That’s the moment we decided to go forward using Linux hosted Azure Functions for this part of the system.
We just had to find out how to deploy them.

Read more →

Use the Copy function to deploy multiple resources after each other

A while ago I was confronted with the fact one of our Azure App Services needed multiple hostname bindings.

I was planning to do this by making multiple Microsoft.Web/sites/hostNameBindings resources, for this specific App Service, in our ARM template. When deploying I was confronted with the following error

{
      "ErrorEntity": {
        "Code": "Conflict",
        "Message": "Cannot modify this site because another operation is in progress. [some more details]",
        "ExtendedCode": "59203",
        "MessageTemplate": "Cannot modify this site because another operation is in progress. Details: {0}",
        "Parameters": [
          "Id: {guid}, OperationName: {someName}, CreatedTime: 3/21/2020 11:13:54 PM, RequestId:{guid}, EntityType: 1"
        ],
        "InnerErrors": null
      }
    }
  ],
  "Innererror": null
}

This is because adding a hostnameBinding can’t be done simultaneously. The way to solve this is by using the copy() function.

To work with this function, you first need an array with data. I’ve named mine hostenameBindings as you can see below.

"variables": {
    "hostnameBindings": [
      "[concat(variables('appServiceCname') ,'.customer.com')]",
      "[concat(variables('appServiceCname') ,'-seconddomain.customer.com')]",
      "[concat(variables('appServiceCname') ,'-another.customer.nl')]"
    ]
}

Now continue creating your ARM template like you’re used to, but when defining the hostnameBindings resource(s), check out this sample.

{
    "type": "Microsoft.Web/sites/hostNameBindings",
    "apiVersion": "2019-08-01",
    "name": "[concat(variables('appServiceName'), '/', variables('hostnameBindings')[copyIndex()])]",
    "location": "[resourceGroup().location]",
    "dependsOn": [
        "[resourceId('Microsoft.Web/sites', variables('appServiceName'))]",
        "[resourceId('Microsoft.Web/certificates', variables('certificate').name)]"
    ],
    "copy": {
        "name": "hostNameBindingsEndpointLoop",
        "mode": "serial",
        "batchSize": 1,
        "count": "[length(variables('hostnameBindings'))]"
    },
    "properties": {
        "siteName": "Sitecore",
        "hostNameType": "Verified",
        "sslState": "SniEnabled",
        "thumbprint": "[parameters('certificateThumbprint')]"
    }
},

Over here I’m telling the resource manager to deploy these resources in serial with a batchSize of 1. This will make sure all hostnameBindings resources will be deployed after each other.
You can use the copyIndex() function to get the N-th element from your array.

Read more →

Creating an Event Grid Topic subscription to a resource in a different resource group

With all of the great services in Azure, it’s easy to set up a nice event-driven architecture. You have Storage Queues, Service Bus Queues & Topics, Event Grid and even more services which can help you accomplish great stuff.
I like the three services mentioned here and most of the time they cover the basics of my messaging infrastructure. One thing you need to do yourself is think about the boundaries of your domains and how to organize all of the services.

What I see happen quite often, and don’t disagree with, is placing all the Custom Topics for Event Grid inside a single, dedicated, resource group. From a developer & operations discovery perspective this makes quite a lot of sense.
There are of course downsides to this approach with the most obvious one being security. If you have access to this resource group, there’s a fairly big chance you have enough permissions to peek inside all of the Event Grid Topics. To lock this down you have to take additional measures which I will not cover over here.

Because we should all be using ARM templates (or something similar) nowadays, it makes sense to create the Event Grid Topics & Subscriptions in your deployment pipeline.
The documentation on this topic is very good and you can figure out how to create a custom topic and subscription quite easily. However, I did get stuck creating a subscription.

Read more →

App Service Resource Provider Access to Keyvault

Recently, I was trying to deploy an Azure App Service which was in need for a couple of certificates, which are stored in Azure Key Vault.

Our ARM template looked very similar to the one below in order to install & configure the certificates in our App Service.

"resources": [
    {
        "type": "Microsoft.Web/certificates",
        "name": "[parameters('certificateName')]",
        "apiVersion": "2019-08-01",
        "location": "[parameters('existingAppLocation')]",
        "properties": {
            "keyVaultId": "[parameters('existingKeyVaultId')]",
            "keyVaultSecretName": "[parameters('existingKeyVaultSecretName')]",
            "serverFarmId": "[parameters('existingServerFarmId')]"
        }
    },
    {
        "type": "Microsoft.Web/sites",
        "name": "[parameters('existingWebAppName')]",
        "apiVersion": "2019-08-01",
        "location": "[parameters('existingAppLocation')]",
        "dependsOn": [
            "[resourceId('Microsoft.Web/certificates', parameters('certificateName'))]"
        ],
        "properties": {
            "hostNameSslStates": [
                {
                    "name": "[parameters('hostname')]",
                    "sslState": "SniEnabled",
                    "thumbprint": "[reference(resourceId('Microsoft.Web/certificates', parameters('certificateName'))).Thumbprint]",
                    "toUpdate": true
                }
            ]
        }
    }
]

When deploying said template, we quickly received a message the deployment had failed.

Resource Microsoft.Web/certificates ‘[myCert]’ failed with message

{ “Code”: “BadRequest”, “Message”: “The service does not have access to ‘/subscriptions/[subscription]/resourcegroups/[resourcegroup]/providers/microsoft.keyvault/vaults/[myVault]’ Key Vault. Please make sure that you have granted necessary permissions to the service to perform the request operation.”, “Target”: null, “Details”: [
{
"Message": "The service does not have access to '/subscriptions/[subscription]/resourcegroups/[resourcegroup]/providers/microsoft.keyvault/vaults/[myVault]' Key Vault. Please make sure that you have granted necessary permissions to the service to perform the request operation."
},
{
"Code": "BadRequest"
},
{
"ErrorEntity": {
"ExtendedCode": "59716",
"MessageTemplate": "The service does not have access to '{0}' Key Vault. Please make sure that you have granted necessary permissions to the service to perform the request operation.",
"Parameters": [ "/subscriptions/[subscription]/resourcegroups/[resourcegroup]/providers/microsoft.keyvault/vaults/[myVault]"
],
"Code": "BadRequest",
"Message": "The service does not have access to '/subscriptions/[subscription]/resourcegroups/[resourcegroup]/providers/microsoft.keyvault/vaults/[myVault]' Key Vault. Please make sure that you have granted necessary permissions to the service to perform the request operation."

Read more →

Static Site With Azure Cdn and Cloudflare

In my last post, I described how to create a Hugo website and what I did to migrate from my Miniblog platform, along with some details on how to create the build & deployment pipeline.

I started by deploying my Hugo websites to a regular Azure App Service. This is a full-blown web application platform. It’s a bit too overpowered for hosting a simple, static, website. As I mentioned in the earlier post, it makes a lot more sense to host static websites on an Azure Storage Account with the Static website hosting. The main reason I postponed this is that I had some issues creating my routing rules.

Moving to static site hosting ASAP

After having migrated to Hugo & the App Service hosting model, I quickly noticed moving to the static site hosting option was quite important. Every time my deployment pipeline was deploying the files to the App Service, the site became unavailable.

page got 404

The pages returned a 404 and when navigating to the root site, the site was just empty. empty site

This is bad, really bad. Of course, I can solve this by deploying the site to a Staging slot and swap with Production when ready. This is quite doable, but not a path I wanted to pursue.

Read more →

Using an Azure Managed Identity to authenticate on a different App Service

A couple of weeks ago, I was tasked to implement authentication between the services we have in our Azure landscape. I knew this can be done by using the Managed Identity, as we were doing this on a project I was involved with in the past.

However, I had never actually done this myself. Most of the time the System Administrators were configuring everything and I just had to copy-paste some Guids in a configuration file. After doing some digging into the matter, it was a bit harder to set this up as I had expected at the start.

Lucky for me, Joonas Westlin has some excellent posts on the matter which have helped me enormously. He was also able to help me out on Stack Overflow when I was stuck and couldn’t find out why the authentication wasn’t working correctly.

Much of what I’ll be writing down here will be similar to Joonas his posts on the matter. I’ll be using some different wording.
The posts I’ve used to learn this stuff were: