Photo by Clint Adair on Unsplash

How To: Reference A Deployed Azure API Management’s Subscription Keys from An Arm Template

Damiene Stewart

--

Scenario

Your team has wisely decided to publish a plethora of APIs via Microsoft Azure’s API Management (APIM) for it’s many benefits.

Now, it’s not at all unusual to want to restrict public access for a set of published APIs. APIM helps you do this through it’s idea of subscriptions/subscription keys. In a nutshell, once enabled, this mechanism ensures that only requests containing a valid subscription key are forwarded to the destination API.

Let’s say your team decided to do this as well. In fact, just to be pedantic, your team has secured each API with a different subscription. To be clear, this means that each API now requires a different subscription for access.

Awesomeness.

In the spirit of keeping everything neat and tidy, you’ve all decided that APIs will never talk to each other directly — all communication is to go through the APIM. Good idea.

The Problem

The only pitfall with this is the subscription keys. Any API that needs to communicate with another will need to have a valid subscription key for the API it is trying to talk to. Just imagine that one of the APIs needs to communicate with a lot (e.g. 20) of the others — it’ll need to know a lot of subscription keys! That’s going to be a nightmare to maintain. Imagine needing to input and update each one of these values manually. Yikes. Furthermore, manually inserting/updating values like this is just asking for trouble at run-time.

The Solution

Some sort of secret store, like the Azure Key Vault, should definitely be leveraged here. You can just copy/paste the subscription keys into the key vault and each API can reference them as needed. Simple, right?

Probably not.

We’d still have the same problem mentioned above. What happens when the subscription keys are rotated (changed)? The values in the key vault will have to be manually updated one by one.

Instead, it would be much more efficient to reference and store the subscription keys from the APIM resource during the key vault’s deployment. That way, if the keys have been rotated, just redeploy.

Let’s explore how we can achieve this when we deploy the key vault via an ARM template.

Setup

I’ve made a resource group called medium-rg with a single, very minimal, API Management resource called medium-apim. Naming things is hard.

View of medium-rg resource group with a single APIM resource.

Note, I’m highlighting the name of the APIM resource because we’ll need to refer to it later in our key vault’s ARM template.

You might be interested in the ARM template I used for deploying the APIM so that you can follow along. If so, check it out:

Subscription Keys

Let’s have a look at the subscription keys. Clicking on the APIM (medium-apim in the image) will take me to a view of that resource. I’ll then have the ability to look at the subscriptions, and subsequently, the subscription keys that have been allocated. It’ll look something like this:

Subscription Key view of APIM resource in the Azure Portal

If you’re not seeing the same columns as in the image above (Display Name, Primary Key, Secondary Key, etc.), click on Columns (near the top in the image above). You’ll get a little pane on the right that helps you select which columns you want to view.

Make sure name is selected.

Customize columns when viewing APIM subscription keys in Azure Portal

Perfect. Now is about the time when you might wonder why the heck there’s already a subscription present with a primary and secondary subscription key.

Well, the name column tells us that this subscription is called master… and that’s fitting since it’s scope is the entire APIM service and it’s created by default. At the time of writing, I don’t think there’s a way to remove or disable it. It doesn’t have to be a huge deal though, just don’t start passing it around and using it in a bunch of places. You’ll probably be alright.

Ideally you would create a subscription with a much narrower scope, and use the subscription keys from that instead.

But, as a wise woman once told the world, “Ain’t nobody got time for that”. I’m definitely just using the master key for this example. That’s just me though.

Deploying A Key Vault

Alright, so let’s deploy our key vault.

The idea is that during the deployment of our key vault, we also want to create a secret in the vault. That value of that secret should be a subscription key of our choice.

There are a few different ways of achieving this. For example, during the deployment of the APIM we could output the value of the subscription key by using the outputs section of the ARM template. The output section of the ARM template is described here.

Perhaps the biggest reason to not do this, is because the value will appear in the deployment history. Not so secret anymore.

A better approach is to obtain a reference to the APIM subscription during deployment of the key vault and simply ask the subscription resource for the value of a particular subscription key.

ARM Template Reference Function

Thankfully, ARM templates have a resource function that’ll help us out. It’s the reference function — please check out the documentation for it. It’ll help us in two key scenarios:

  1. You’re trying to obtain a reference to a resource being deployed in the same ARM Template.
  2. You’re trying to obtain a reference to a previously deployed resource.

Same-Template Reference

As mentioned in the documentation, you just have to provide the resource name to the reference function, and boom! You’re done, you have a usable reference to that resource.

But that’s if you’re deploying the APIM subscription and trying to obtain a reference to it within the same ARM template. This isn’t our scenario since the APIM is already deployed. So we’re just going to jump into the next section. Don’t worry though, it’s pretty similar, so reading through the next section will help with this scenario as well.

*Previously Deployed Resource

To request a subscription key value from the deployed APIM, we need to provide the reference function with a resource id and an app version, according to the documentation.

We’ll need the help of an additional function here. The resourceId function.

According to the resourceId function documentation, we only need to provide the resource type and resource name as parameters.

*Note: if we were deploying to a different resource group, we’d need to provide that resource group name as a parameter. Or, if we were deploying to a different subscription, we’d need to provide both the subscription id, and the resource group name as parameters.

So, we’ll get the resourceId with this call:

resourceId('Microsoft.ApiManagement/service/subscriptions', 'medium-apim', 'master')

Note how I’m passing the name of the APIM (medium-apim) as well as the name of the subscription that I want the subscription key for (master).

We’ll pass the result of this to the reference function like this:

reference(resourceId('Microsoft.ApiManagement/service/subscriptions', 'medium-apim', 'master'), '2019-01-01').primaryKey

Key Vault ARM Template

Key Vault Secrets List View

Dive into that secret, medium-kv-secret, and see that it’s value is the master subscription’s primary key.

Conclusion

Copying and pasting values isn’t always a bad thing, but it should definitely raise some flags and prompt the question of whether or not it’s actually necessary.

In this article, we explored how to avoid copying and pasting a subscription key from an APIM resource to a key vault. Instead, we’ve allowed the key vault to grab the subscription key directly from the APIM at deployment time.

Share to save an engineer from having to track down issues caused by incorrectly copying/pasting subscription keys.

Thanks for reading!

Consider hitting that follow button. Also, follow me on Twitter @damienestewart. I can’t promise I’ll say anything interesting, but it’ll give me that good “new follower” feeling :).

--

--

Damiene Stewart

Software engineer, writer, avid sleeper, and some other stuff. I like long walks on the beach too. Not even kidding.