Basic walkthru setup of Azure Front Door with APIm

When I recently setup an Azure Front Door (AFD) I found that there was no good for dummies or just make it work kind of articles, and that is why I write this. That said, if you are looking for more in depth documentation I recommend this page, and if you are looking for an in depth example and setup with APIm you should check out this GitHub repo by Paolo Salvatore.

Finding AFD

The first task is to find Azure Front Door. I usually use the search bar at the top of the page and the select the marketplace option.

Configuring AFD

Basics

First you need to assign or create a resource group for the new AFD. Note that the location is only for the resource group and not the AFD. The ADF service is a global service and as such have no location. That is one of its prime features.

Note The location for my resource group in the picture is not valid. Choose any under Recommended in the dropdown.

Click the Next:Configuration button to continue.

Configuration

When you setup an AFD for the first time, you get a nice Wizard to help you along. Start by clicking the plus-sign under Frontend/Domains.


In this step you need to add a frontend host, which sounds tricky but is really only the web address that the AFD will have once you publish it. This name needs to be globally unique. I have chosen mikaelsandblog so the address will be http://mikaelsandblog.azurefd.net when I publish it.

The other two options are out of scope for this blogpost but they have no effect on what we are trying to do.

Backend pools

This is the second step. Just click the plus-sign again. Here you will add pointers to the APIm instances you want to expose using AFD. The name pool refers to the pool of service endpoints that AFD can pick from to direct an incoming call.

Name

Start by giving the pool a name, like MyAPIms or something. When you do this properly, you might want to use a better name.

Add a backend

Click on the + Add a backend link to get this form

In the dropdown, chose API Management. This populates the form with the APIm instances available to you in your subscriptions, which is awesome! Simply chose the subscription and APIm instance you want, and you would probably also leave the port configuration as they are.

Should you need to point to an instance which is not in the same subscription, you should use the Custom Host Option. Simply add the host FQDN for your APIm instance in the Backend host name field. In my case this is mikaelsand.azure-api.net and leave all the other settings as is.

Priority and weight

If you are looking for the simplest of setups you can skip this part.
In some scenarios these settings are really important. In my case I needed to demonstrate the use of AFD as a failover service. This meant that one APIm instance should always be preferred if it is available. The basic setting for priority and weight points to a round robin pattern where all endpoints are treated equally. In order to make one endpoint be the preferred I simply gave that one the max setting in both, so priority=1 and weight=1000 made sure that one APIm was called as often as possible.

If this is not in the scope of your scenario, just leave the settings as is.

Routing rules

The last step is to setup routing for your AFD. This is very useful if you have several services behind your AFD, but that is not the scope of this post. Simply click the plus sign and review the form.

The settings should be enough to get your first call thru, so simply click Add.

Provisioning

You should now be able to end the configuration of AFD and provision it from Azure. It will not even take a minute.

Testing it out

If you need some tips on how to make sure it works, you can keep reading.
To make sure that everything works as it is supposed to, you can fire up Postman or VS Code. First, try to call your APIm directly to know that everything is working as intended:

The call

GET https://mikaelsand.azure-api.net/echo/resource?param1=sample
Ocp-Apim-Subscription-Key: xyzxyzxyz

The response

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 0
Expires: -1
Accept-Encoding: gzip,deflate
Host: echoapi.cloudapp.net
User-Agent: vscode-restclient
ocp-apim-subscription-key: xyzxyzxyz
X-Forwarded-For: 217.208.192.204
X-AspNet-Version: 4.0.30319
X-Powered-By: Azure API Management - http://api.azure.com/,ASP.NET
Date: Thu, 30 Apr 2020 09:06:33 GMT
Connection: close

Then you change the host address in the URI to the host address you assigned earlier. For me I replaced mikaelsand.azure-api.net with mikaelsandblog.azurefd.net. The you call the API once again.

The call

GET https://mikaelsandblog.azurefd.net/echo/resource?param1=sample
Ocp-Apim-Subscription-Key: xyzxyzxyz

The response

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Via: 1.1 Azure
Expires: -1
Accept-Encoding: gzip,deflate
Host: echoapi.cloudapp.net
User-Agent: vscode-restclient
ocp-apim-subscription-key: xyzxyzxyz
X-Forwarded-For: 217.208.192.204,147.243.71.16
X-Azure-ClientIP: 217.208.192.204
X-Azure-Ref: 0eZWqXgAAAAArCUZJElgDSJxnlGMAYizAU1RPRURHRTA4MTUAMGYyMTViODAtNjk3OS00YzU3LWIzM2ItOTYyODI3NjZiYjQ5
X-Forwarded-Host: mikaelsandblog.azurefd.net
X-Forwarded-Proto: https
X-Azure-RequestChain: hops=1
X-Azure-SocketIP: 217.208.192.204
X-Azure-FDID: 0f215b80-6979-4c57-b33b-96282766bb49
X-AspNet-Version: 4.0.30319
X-Powered-By: Azure API Management - http://api.azure.com/,ASP.NET
Date: Thu, 30 Apr 2020 09:08:09 GMT
Connection: close
Content-Length: 0

You should get the same answer back, with some additional headers. If you do, everything is working fine.
All those X-headers are set by AFD and can be used for tracking and debugging calls. The sample put up by Paolo examines this.

If you do not have access to any API in the APIm you are trying to call you can always your the status service we used under the health probe section above.

The call

GET https://mikaelsandblog.azurefd.net/status-0123456789ABCDEF

The response

HTTP/1.1 200 Service Operational
Content-Type: application/json
X-Azure-Ref: 0PJqqXgAAAACTmVtpuYfiQqT3XHQhG9jLU1RPRURHRTA4MjIAMGYyMTViODAtNjk3OS00YzU3LWIzM2ItOTYyODI3NjZiYjQ5
Date: Thu, 30 Apr 2020 09:28:28 GMT
Connection: close
Content-Length: 0

In closing

There are a lot of nice and useful features in AFD. I suggest that the next thing you look at are routing rules or custom domains.

If you want to get your teeth into it, I think the best place to start is the AFD FAQ.

Calling APIm consumption SKU from Logic App

There is a problem when you want to call an API hosted in an Azure API management (APIm) instance if it is a consumption SKU.
Getting around it is easy.

The issue

Lets say you need to call a service you have made. That service has to be hosted behind an Azure API management instance. There might be many reasons, but the main one is that the service need to be protected using APIm.

You create a new Logic App and you want use the built in connector for APIm.
file
You find the consumption instance and select it. The API you created shows up in the Logic App.
file
In my case the API is simply calling a dummy Logic App.

You fill what you need in order to connect to the API. In my case I only need a SubscriptionID.
file
You click save and you will get this error:
file

Failed to save Logic App <your name here>. The API Management service hosting the API <pointing to your APIm instance> could not be found

My toughts

I think this is due to how the connector works in Logic Apps. The connector gets its configuration in a different way than how it saves that configuration. An APIm consumption SKU is different from a regular one. It does not have any external IP-address, since it is a shared service. Several consumption instances are probably hosted on the same servers which makes me think that is why the Logic App cannot find it when it saves.

I would consider this a bug, rather than not supported.

The solution

You have to work around the problem and use the ever useful HTTP action. You can always call the API using its DNS name (or address of you prefer).
file

Error when using ServiceBus Relay

We got a very strange error message when calling an on-prem service using the ServiceBus Relay connected to an Azure Function.

Scenario

The scenario was setup according to the official documentation. The relay can be used as an alternative to the OnPremise Data gateway in scenarios where you don’t need the adapter connectivity. You have a limited subset or can do your own coding if you need something specific.

Copyright Microsoft

The error

Executed 'Send' (Failed, Id=GUID_HERE) An attempt was made to access a socket in a way forbidden by its access permissions.

Obviously, there are some security issues.

The search

One of these errors makes you visit Mr Google. He turned up a lot of answers, all related to a local firewall and people having built their own socket services. None of the answers applied to us.

We tried regenerating keys and re-registering the connection but that did not work.

The solution

The service developer had provided us with an IP-address as a host address. When we did a DNS lookup, we found the name of the server. We simply updated the host address in the relay connection, and it worked!

The lesson

When using Azure Relay, don’t use the service IP-address.

Assigning custom API keys in APIm

When exposing an API in APIM you typically put it in a Product. You then create a subscription for that product, making it possible for consumers to use your Product, and for you to keep track of that usage. Sometimes, you might need to use a custom key, and not the key assigned by API manager.

Generating keys

You know that you typically do not need to generate keys for a subscription, keys are generated automatically when you create the subscription.

If you choose to, you can view the keys by clicking the three dots at the end of the row.

The key usually looks something like “1f9400c493e4403a807c3002dfc5cbb9”, and if you want to you can regenerate the primary or secondary keys.

What if you needed to set that key instead? There might be reasons for it. For me, I needed to make sure the key had the same value between two environments (don’t ask).

Assigning keys

In order to assign keys, you need to use the APIM Management API (still the worst name since ever), but using that, it is very easy actually.

Enable the Management API

In order how to enable the API and learn how to generate access tokens, visit this page. In the end you should have an access token that looks something like

SharedAccessSignature integration&202003131741&EwaL4wDY7o8om3c… 

This can be used as an authentication header in Postman to call the APIs. Note that the access token key will only work if you target the specific management API. More information below.

Another thing to know is that the Management API is not supported for the consumption model of APIm.

Find the right API to use

There are a lot of APIs connected to APIm. The complete list can be found here. The one we are looking for is called Subscription Update.

The subscription update API

one is a little special as it uses the http verb PATCH. This means that only fields sent in the body will be updated. The brother of this verb is PUT that usually wants an entire data object and updates everything, always.

The easiest way to use this is by using the access token generated above. This means that the URI used in the documentation is incorrect. If you want to use that API you need to access it using a Bearer Token. The path pointed out by the documentation is:

https://management.azure.com/subscriptions etc.

The one you need to use (the original access model) is:

https://{{serviceName}}.management.azure-api.net/subscriptions etc

Service name is the name of you APIm instance.

Using the API with Postman

I used postman to update the keys. You can actually do this from the API documentation portal, by clicking the “Try it” button in the documentation page and signing in, but I used postman and the original access model.
I setup postman using a environment variables and that resulted in this URL:

https://{{serviceName}}.management.azure-api.net/subscriptions/{{subscriptionId}}/resourceGroups/{{resourceGroupName}}/providers/Microsoft.ApiManagement/service/{{serviceName}}/subscriptions/test-1?api-version=2019-01-01

Test-1 is the ID of the subscription I am trying to assign keys for.
After constructing the URL you need to create a body that patches the properties PrimaryKey and SecondaryKey.

{
"properties": {
"primaryKey":"MyKey1",
"secondaryKey":"MyKey2"
}
}

Lastly you need to authenticate. Do this by adding an Authorization header and put in the access token you got earlier. All this should result in the following PATCH.

PATCH  https://myapis.management.azure-api.net/subscriptions/e29827ab-0759-4d6d-80bc-198e82f6ae68/resourceGroups/myresourcegroupname/providers/Microsoft.ApiManagement/service/myapis/subscriptions/test-1?api-version=2019-01-01

Authentication SharedAccessSignature integration&202003131741&EwaL4wDY7o8om3c…

{
"properties": {
"primaryKey":"MyKey1",
"secondaryKey":"MyKey2"
}
}

Examining the results

If you got back a 204 No content, that means success!

Go back into the APIm portal and find the subscription and look at the keys. They should now have the value you assigned, however limited and not smart.

Further research

Remember to use long and complex keys. I have not yet examined limits, like what chars are allowed, how long can a key be and so on.
Good luck and let me know.

Getting the DateTime from unix epoch in Logic Apps

Relating to my other post on Get unix epoch from DateTime in Logic Apps, there is a much simpler way to calculate UtcNow from a Unix timestamp. There is even no real math involved. All you do is make use of the built in function addToTime.

Here is the expression: addToTime('1970-01-01', 1508852960,'second')

So if you receive a JSON body with a tag called UnixTimeStamp, containing the Unix timestamp it will look like
addToTime('1970-01-01', int(triggerBody()?['UnixTimeStamp']),'second')

Hope you can make use of it.