xmlazureterraformterraform-provider-azureapim

How to add policies for different APIs as per api requirement


I am writing a terraform code where I am writing xml as well. I have two APIs and different policy requirements. I am trying to achieve it as below code but it doesn't help. Does anyone know how to add policies according to the APIs requirement?

<choose>
     ########## API ONE ###########
     <when condition="@(context.Request.Headers.GetValueOrDefault("ApiKey") == "Default")">
         <rate-limit-by-key calls="10" renewal-period="60" counter-key="@(context.Request.IpAddress)" />
     </when>
     ########## API TWO ###########
     <when condition="@(context.Subscription.Name.Contains("API_name") and context.Request.Headers.GetValueOrDefault("ApiKey") == "Default")">
          <rate-limit-by-key calls="2000" renewal-period="60" counter-key="@(context.Request.Headers.GetValueOrDefault("Authorization","").AsJwt()?.Subject)" />
      </when>
      <otherwise>
           <rate-limit-by-key calls="10000" renewal-period="60" counter-key="@(context.Subscription.Id)" />
      </otherwise>

Solution

  • Resource azurerm_api_management_api_policy manages an API Management API Policy.

    You can:

    Using separate policy files for each API

    Advantages:

    Disadvantages:

    Example - consider the following folder structure:

    policies/
      foo-policy.xml
      bar.policy.xml
    

    And then create azurerm_api_management_api_policy resources for each policy.

    Example:

    resource "azurerm_api_management_api_policy" "foo" {
      api_name            = "foo-api"
      api_management_name = var.api_management_name
      resource_group_name = var.resource_group_name
    
      xml_content = file("${path.module}/policies/foo-policy.xml")
    }
    
    resource "azurerm_api_management_api_policy" "bar" {
      api_name            = "bar-api"
      api_management_name = var.api_management_name
      resource_group_name = var.resource_group_name
    
      xml_content = file("${path.module}/policies/bar-policy.xml")
    }
    

    Using one template file for the policies

    As an alternative, you can have one single template for the API policies and use templatefile to generate the desired content.

    Advantages:

    Disadvantages:

    Example - file policies/policy-template.tpl

    <choose>
      %{ if api_version == "one" ~}
      <when condition='@(context.Request.Headers.GetValueOrDefault("ApiKey") == "Default")'>
        <rate-limit-by-key calls="10" renewal-period="60" counter-key='@(context.Request.IpAddress)' />
      </when>
      %{ endif ~}
      %{ if api_version == "two" ~}
      <when condition='@(context.Subscription.Name.Contains("API_name") and context.Request.Headers.GetValueOrDefault("ApiKey") == "Default")'>
        <rate-limit-by-key calls="2000" renewal-period="60" counter-key='@(context.Request.Headers.GetValueOrDefault("Authorization","").AsJwt()?.Subject)' />
      </when>
      <otherwise>
          <rate-limit-by-key calls="10000" renewal-period="60" counter-key="@(context.Subscription.Id)" />
      </otherwise>
      %{ endif ~}
    </choose>
    

    Terraform code:

    resource "azurerm_api_management_api_policy" "one" {
      api_name            = "one-api"
      api_management_name = var.api_management_name
      resource_group_name = var.resource_group_name
    
      xml_content = templatefile("${path.module}/policies/policy-template.tpl", {
        api_version = "one"
      })
    }
    
    resource "azurerm_api_management_api_policy" "two" {
      api_name            = "two-api"
      api_management_name = var.api_management_name
      resource_group_name = var.resource_group_name
    
      xml_content = templatefile("${path.module}/policies/policy-template.tpl", {
        api_version = "two"
      })
    }