How to amend policy associated with Azure APIM APIs or operations with additional policy in automated way

120 Views Asked by At

I am trying to have an automated way to amend or apply additional policy on APIs or operations scope of Azure APIM and in my script i am able to read a variable $inbound or $outbound or $backend or $onerror as per user inputs. Now i am trying to apply this newly given policy to the API or Operations, where some global policies/ existing policies already applied. How to add or amend these newly adding policies to the right session of the API or operations, without duplication them if the policy is already existing?

for f in $policy_ ; do
  if [[ $(eval echo \$${f}_name) == "ipfilter" ]]; then
    echo " given policy name is ipfilter "

    if [[ $(eval echo \$${f}_scope) == "api" ]]; then
      echo "decided the scope of Ipfilter policy as api "
    fi

    if [[ "$(eval echo \$${f}_apiname)" ]]; then
       echo "export the policy for the api $(eval echo \$${f}_apiname)"
       curl -H "Content-Type: application/json" -H "Authorization: Bearer $accessToken" "https://management.azure.com/subscriptions/xxxxx/resourceGroups/xx-rg/providers/Microsoft.ApiManagement/service/xxx-apim/apis/myapi/policies/policy?effective=true&format=xml&api-version=2022-08-01" > effectivepolicy.xml
    fi

    if [ -z "$(eval echo \$${f}_inboundsession)" ]; then
        echo 'the inbound session is not present'
    fi
    if [[ "$(eval echo \$${f}_inboundsession)" ]]; then
      echo 'the inbound session is present and append the policy settings to inbound'
      inbound=$(printf "$(eval echo \$${f}_inboundsession)")
       echo "$inbound"
       Add the $inbound to the inbound session of policy.xml if its not existing and apply back 
    fi

For example here $inbound variable value is

<ip-filter action="allow">
 <address-range from="xxxxx" to="yyy" />
</ip-filter> 

Below is the extracted effective policy sample from the api scope and need to amend and apply the same api with above newly added policy without duplication.

<policies>
    <inbound>
            <!--base: Begin Global scope-->
            <cors xxxxxxxxxx="true">
            ****************************
            ****************************
            ****************************
            </cors>
            <!--base: End Global scope-->
    </inbound>
    <backend>
            <!--base: Begin Global scope-->
             ****************************
             ****************************
             ****************************
            <!--base: End Global scope-->
    </backend>
    <outbound>
            <!--base: Begin Global scope-->
            ****************************
            ****************************
            ****************************
            ****************************
            <!--base: End Global scope-->
    </outbound>
    <on-error>
            <!--base: Begin Global scope-->
            ****************************
            ****************************
            ****************************
            <!--base: End Global scope-->
    </on-error>

Output of the custom policy file after trying the @khtesam Afrin Tried solution

parser script tried.

input of policy file in yaml


- name: ipfilter
  scope: api
  apiname: xxxxx
  inboundsession: |
                <ip-filter action="allow">
                    <address-range from="xxxxx" to="yyyy" />
                </ip-filter>
  outboundsession: |
                <ip-filter action="allow">
                    <address-range from="xxxxx" to="vvvv" />
                </ip-filter>

policy Script Tried


source parse_yaml.sh
eval $(parse_yaml input.yaml policy)
echo ".............Eval Result..............................."
for f in $policy_ ; do eval echo \$f \$${f}_ ; done
echo "............Eval Result................................"

for f in $policy_ ; do
  if [[ $(eval echo \$${f}_name) == "ipfilter" ]]; then
    echo " given policy name is ipfilter "

    if [[ $(eval echo \$${f}_scope) == "api" ]]; then
      echo "decided the scope of Ipfilter policy as api "
    fi

    if [[ "$(eval echo \$${f}_apiname)" ]]; then
       echo "export the policy for the api $(eval echo \$${f}_apiname)"
       curl -H "Content-Type: application/json" -H "Authorization: Bearer $accessToken" "https://management.azure.com/xxxx/providers/Microsoft.ApiManagement/service/ssssssss/apis/xxxxxxxxx/policies/policy?effective=true&format=xml&api-version=2022-08-01" > policy.xml
    fi

    if [ -z "$(eval echo \$${f}_inboundsession)" ]; then
        echo 'the inbound session is not present'
    fi
    if [[ "$(eval echo \$${f}_inboundsession)" ]]; then
      echo 'the inbound session is present and append the policy settings to inbound'
      inboundPolicy=$(printf "$(eval echo \$${f}_inboundsession)")
      echo "$inboundPolicy"
      if grep -qF "$inboundPolicy" policy.xml; then
        echo "Policy already exists in the inbound session."
      else
        # Insert the new policy into the existing policy XML
        echo "updating existing policy with new policy content"
        awk -v policy="$inboundPolicy" '/<\/inbound>/ && !p {print policy; p=1} 1' policy.xml > temp.xml
        mv temp.xml policy.xml
      fi
    fi

The parser script output for the variable inboundPolicy


<ip-filter action="allow">
 <address-range from="xxxxx" to="yyy" />
</ip-filter> 

OutPut Of the Script


.............Eval Result...............................
policy1 policy1_name policy1_scope policy1_apiname policy1_inboundsession policy1_outboundsession
............Eval Result................................
 given policy name is ipfilter
decided the scope of Ipfilter policy as api
export the policy for the api xxxxxxx
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
the inbound session is present and append the below policy settings to inbound
<ip-filter action="allow">
 <address-range from="xxxxx" to="yyyyyyy" />
 </ip-filter>
updating existing policy with new policy content
the outbound session is present
the backend session is not present

Output of the custom policy file


<policies>^M
        <inbound>^M
                <!--base: Begin Global scope-->^M
                <cors axxxxxxx="true">^M
                        <xxxxxxx>^M
                                <origin>aaaaaaaaaaa</origin>^M
                                <origin>bbbbbbbbbbb</origin>^M
                                <origin>cccccccccccc</origin>^M
                        </xxxxxxx>^M
                </cors>^M
                <!--base: End Global scope-->^M
<ip-filter action="allow">
 <address-range from="xxxx" to="yyyy" />
 </ip-filter>
        </inbound>^M
        <backend>^M
                <!--base: Begin Global scope-->^M
                <forward-request />^M
                <!--base: End Global scope-->^M
1

There are 1 best solutions below

16
Ikhtesam Afrin On BEST ANSWER

I am using the below script to check for duplication of the policy in effective policy before adding it.

#!/bin/bash

# Set variables
accessToken="eyJ0eXAi******qaoJinw"
subscriptionId="{subscriptionId}"
resourceGroupName="{resourceGroupName}"
apimServiceName="{apimServiceName}"
apiName="echo-api"
inboundPolicy='<set-header name="Test" exists-action="override">
            <value>Hi, Ikhtesam</value>
        </set-header>'

# Fetch existing effective policy XML
curl -H "Authorization: Bearer $accessToken" \
     "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$apimServiceName/apis/$apiName/policies/policy?effective=true&format=xml&api-version=2022-08-01" \
     > policy.xml

if grep -qF "$inboundPolicy" policy.xml; then
    echo "Policy already exists in the inbound session."
else
    # Insert the new policy into the existing policy XML
    awk -v policy="$inboundPolicy" '/<\/inbound>/ && !p {print policy; p=1} 1' policy.xml > temp.xml
    mv temp.xml policy.xml

    # Update the API's policy with the modified XML
    curl -X PUT \
  "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$apimServiceName/apis/$apiName/policies/policy?api-version=2022-08-01" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $accessToken" \
  -d '{
    "properties": {
      "format": "xml",
      "value": "'"$(sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' policy.xml)"'"
    }
  }'
    echo "Policy added to the inbound session."
fi

By executing this script, I am able to add the set-header policy successfully.

enter image description here

When I ran my script for set-header policy again, I got below output.

enter image description here

Script for taking the inputs from yaml file.

#!/bin/bash

# Set variables
accessToken="eyJ0*****yXG6craOOQG3g"
subscriptionId="b823f"
resourceGroupName="RG_Name"
apimServiceName="Service_Name"
apiName="echo-api"

source parse_yaml.sh
eval $(parse_yaml input.yaml policy)
echo ".............Eval Result..............................."
for f in $policy_ ; do eval echo \$f \$${f}_ ; done
echo "............Eval Result................................"

for f in $policy_ ; do
  if [[ $(eval echo \$${f}_name) == "setheader" ]]; then
    echo " given policy name is setheader "

    if [[ $(eval echo \$${f}_scope) == "api" ]]; then
      echo "decided the scope of setheader policy as api "
    fi

    if [[ "$(eval echo \$${f}_apiname)" ]]; then
       echo "export the policy for the api $(eval echo \$${f}_apiname)"
       curl -H "Content-Type: application/json" -H "Authorization: Bearer $accessToken" "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$apimServiceName/apis/$apiName/policies/policy?effective=true&format=xml&api-version=2022-08-01" > policy.xml
    fi

    if [ -z "$(eval echo \$${f}_inboundsession)" ]; then
        echo 'the inbound session is not present'
    fi
    if [[ "$(eval echo \$${f}_inboundsession)" ]]; then
      echo 'the inbound session is present and append the policy settings to inbound'
      inboundPolicy=$(printf "$(eval echo \$${f}_inboundsession)")
      echo "$inboundPolicy"
      if grep -qF "$inboundPolicy" policy.xml; then
        echo "Policy already exists in the inbound session."
      else
        # Insert the new policy into the existing policy XML
        awk -v policy="$inboundPolicy" '/<\/inbound>/ && !p {print policy; p=1} 1' policy.xml > temp.xml
        mv temp.xml policy.xml

        # Update the API's policy with the modified XML
        curl -X PUT \
        "https://management.azure.com/subscriptions/$subscriptionId/resourceGroups/$resourceGroupName/providers/Microsoft.ApiManagement/service/$apimServiceName/apis/$apiName/policies/policy?api-version=2022-08-01" \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer $accessToken" \
        -d '{
            "properties": {
                "format": "xml",
                "value": "'"$(sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' policy.xml)"'"
            }
        }'
      fi
    fi
  fi
done

Output-

enter image description here

In this way, you can add the policy without duplication.