Azure Bicep: How to Provision an API Management

Azure Bicep: How to Provision an API Management

Azure API Management is a fully managed service that helps organizations publish, secure, transform, maintain, and monitor APIs. It provides a scalable and secure environment for API hosting, allowing developers to create, manage, and analyze APIs in a streamlined manner. While there are many benefits to using a tool like this, there are some challenges, such as keeping all our environments in sync, particularly if we are managing this task manually. To address this particular issue, we can use Azure Bicep for provisioning API management and maintaining consistency across our environments.

Pre-requisites

Concepts

Before diving into the details, let's clarify some key concepts:

  • Operation: An action performed on a resource.

  • API: Represents a set of operations.

  • Product: A collection of one or more APIs.

  • Subscription: Permissions to access a product or API.

  • Policies: Collection of statements executed sequentially on the request or response to change the behavior of an API.

Creating an API Management Instance

Create a main.bicep file containing the following content:

param apiManagementName string
param location string = resourceGroup().location

resource apiManagementInstance 'Microsoft.ApiManagement/service@2020-12-01' = {
  name: apiManagementName
  location: location
  sku:{
    capacity: 0
    name: 'Consumption'
  }
  properties:{
    virtualNetworkType: 'None'
    publisherEmail: 'raulnq@gmail.com'
    publisherName: 'MyCompany'
  }
}

resource apiManagementInstancePolicy 'Microsoft.ApiManagement/service/policies@2020-12-01' = {
  name: 'policy'
  parent: apiManagementInstance
  properties: {
    value: '<policies><inbound></inbound><backend><forward-request/></backend><outbound></outbound></policies>'
    format: 'xml'
  }
}

We are creating an API Management instance with a Consumption SKU and its corresponding policy.

Creating an API

Add the following content to the main.bicep file to create one of the many APIs we can define. In this case, we are using https://restcountries.com/ API:

resource apiManagementApi 'Microsoft.ApiManagement/service/apis@2023-03-01-preview' = {
  parent: apiManagementInstance
  name: 'countries-api'
  properties: {
    apiRevision: '1'
    displayName: 'Contries API'
    description: 'Contries API'
    subscriptionRequired: true
    serviceUrl: 'https://restcountries.com/'
    subscriptionKeyParameterNames: {
      header: 'Ocp-Apim-Subscription-Key'
      query: 'subscription-key'
    }
    protocols: [
      'https'
    ]
    path: ''
  }
}

resource apiManagementApiPolicy 'Microsoft.ApiManagement/service/apis/policies@2020-12-01' = {
  name: 'policy'
  parent: apiManagementApi
  properties: {
    value: '<policies> <inbound> <base /> <set-header name="X-API-KEY" exists-action="append"> <value>${thirdPartyApiKey}</value> </set-header> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>'
    format: 'xml'
  }
}

Adding an Operation

Add the following content to the main.bicep file to add an operation that retrieves information about a country based on its name:

resource apiManagementOperationGetCountry 'Microsoft.ApiManagement/service/apis/operations@2023-03-01-preview' = {
  parent: apiManagementApi
  name: 'get-countries'
  properties: {
    displayName: '/v3.1/name/{name} - GET'
    method: 'GET'
    urlTemplate: '/v3.1/name/{name}'
    templateParameters: [
      {
        name: 'name'
        type: 'string'
        required: true
      }
    ]
    request: {
      queryParameters: [
        {
          name: 'fullText'
          type: 'boolean'
        }
      ]
    }
    responses:[
      {
        statusCode: 200
        description: 'Success'
        representations:[
          {
            contentType:'application/json'
          }
        ]
      }
    ]
  }
}

resource apiManagementOperationGetCountryPolicy 'Microsoft.ApiManagement/service/apis/operations/policies@2020-12-01' = {
  name: 'policy'
  parent: apiManagementOperationGetCountry
  properties: {
    value: '<policies><inbound><base/></inbound><backend><base/></backend><outbound><base/></outbound><on-error><base/></on-error></policies>'
    format: 'xml'
  }
}

Defining a Product

Add the following content to the main.bicep file to define a product and the link against our API:

resource product 'Microsoft.ApiManagement/service/products@2020-12-01' = {
  name: 'product'
  parent: apiManagementInstance
  properties: {
    displayName: 'Product'
    description: 'Product'
    subscriptionRequired: true
    approvalRequired: true
    state: 'published'
    subscriptionsLimit: 1
    terms: 'These are the terms of use ...'
  }
}

resource productPolicies 'Microsoft.ApiManagement/service/products/policies@2020-12-01' = {
  name: 'policy'
  parent: product
  properties: {
    value: '<policies><inbound><base/></inbound><backend><base/></backend><outbound><base/></outbound><on-error><base/></on-error></policies>'
    format: 'xml'
  }
}

resource linkApiToProduct 'Microsoft.ApiManagement/service/products/apiLinks@2023-03-01-preview' = {
  name: 'link'
  parent: product
  properties: {
    apiId: apiManagementApi.id
  }
}

Creating a Subscription

And finally, add a subscription to our product by including the following content in the main.bicep file:

resource developerSubscription 'Microsoft.ApiManagement/service/subscriptions@2023-03-01-preview' = {
  parent: apiManagementInstance
  name: 'developer'
  properties: {
    scope: '/products/${product.id}'
    state: 'active'
    displayName: 'developer'
  }
}

Deploying the script

First, create a resource group using the following command:

az group create -l eastus -n MyResourceGroup

And deploy the main.bicep file:

az deployment group create --resource-group MyResourceGroup --template-file .\main.bicep

There are several other resources to create, such as users, groups, schemas, etc. However, we believe this is a good starting point for using Azure Bicep with API Management. Thanks, and happy coding.