Giter VIP home page Giter VIP logo

api-management-policy-snippets's Introduction

Azure API Management Policy Snippets

Examples

The examples/ folder contains policy examples contributed by the product team and the user community. The samples are meant to be re-used verbatim, provide inspiration or serve as learning aids. Some of them are parameterized using Named Values (formerly known as Properties), which look like this: {{some-value}}. When using parametrized samples, you will have to either define relevant Named Values or replace them with values in place.

Policy expressions cheat-sheet

The policy-expressions folder contains a cheat-sheet with common policy expressions that are often used when authoring Azure API Management policies.

Visual Studio Code snippets

The vscode-snippets/ folder contains user snippets for Visual Studio Code. User snippets are helpful for streamlining workflow and simplifying document editing with autocomplete and easy navigation. Please, refer to the Visual Studio Code documentation on how to use them.

Azure API Management VS Code User Snippet 1

Azure API Management VS Code User Snippet 2

Azure API Management VS Code User Snippet 3

Helpful Links

To learn about Azure API Management go here.

Contributing

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

api-management-policy-snippets's People

Contributors

adrianhall avatar dlepow avatar falrnacn avatar francozuca avatar gfchaves avatar glav avatar graemefoster avatar jftl6y avatar jochimvandooren avatar joeyeng avatar kobulloc-msft avatar lfalck avatar martinpankraz avatar miaojiang avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar mike-urnun-msft avatar mikebudzynski avatar mumurug-msft avatar nbarrasson avatar nzthiago avatar orangetoken avatar pkpaul avatar pramodvalavala-msft avatar simonkurtz-msft avatar solankisamir avatar stuartleeks avatar tomkerkhove avatar vladvino avatar your-azure-coach avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api-management-policy-snippets's Issues

PolicyFragment ARM Template deployment fails - The policy fragment is not a valid XML:

Bicep Code

param APIMName string

resource policyFragment2 'Microsoft.ApiManagement/service/policyFragments@2021-12-01-preview' = { 
  name: '${APIMName}/SetBasicAuthHeader'
  properties: {
    description: 'Sample desc'
    format: 'xml'
    value: './SetBasicAuthHeader.xml'
  }
}

Fragment
Simplified to bare minimum

<fragment>
</fragment>

CLI command to deploy

az deployment group create --resource-group APIM --template-file singlepolicyfragmentdeploy.bicep --parameters APIMName=karlrissapim

Error

{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"BadRequest","message":"{\r\n \"error\": {\r\n \"code\": \"ValidationError\",\r\n \"message\": \"The policy fragment is not a valid XML: Data at the root level is invalid. Line 1, position 1.\",\r\n \"details\": null\r\n }\r\n}"}]}}

Additional Information
We tried deploying from an Azure Storage account in case it needed a URI to reference the policy fragment, failed with the same error message.

We manually created a policy fragment in the portal, then saved the configuration to the repository and cloned the repository locally to inspect the policy fragment to see if there was a documentation bug and the fragment structure was different, the repository does not contain policy fragments so we were unable to view.

We also tried both format types, XML and RawXML.

Lastly, we also compiled bicep to arm and tried again, receiving the same error message.

Possibility to amend multi value header e.g. Set-Cookie?

Hi,

Is there any possibility to loop through multi-value request header and change it?

<when condition="@(context.Response.Headers.ContainsKey("Set-Cookie"))">
  <set-header name="Set-Cookie" exists-action="override">
      ... How can I loop through multi value header and update each value of context.Request.Headers["Set-Cookie"]
  </set-header>
</when>

Add Policy Fragment Examples

It could be helpful to have a dedicated section in this repo for valuable policy fragments that show the policy fragment itself and an implementation thereof.

@elbarnit

Aren't APIM's inbound policies able to read Redis Cache keys set externally?

We have a customer in West Europe and am setting up an APIM instance for them in the Central France region. We're running the REST API and the backend in West US. It takes ~20 seconds for a ~2MB file to travel from West US to Central France. In order to improve that delay, I'm attempting to write the file into a Redis instance that's located in Central France and have APIM's inbound policy read it from Redis and return it right away if present, instead of calling our West US located REST API. I could not get this to work, so am wondering what am I missing or is such a scenario not supported by APIM? A key in Redis is key in Redis and should be readable by any service that has access rights to the Redis instance.

I set the APIM's Managed Identity to have "Redis Contributor" permissions on the Redis instance.

I did find earlier #43 and am caching in the backend using the "2_" prefixed key and lookup in APIM's inbound policy using the bare key. It does not work. I did use VS Code's Azure Cache extension to verify that the "2_" prefixed key is present in the Redis cache.
image

I did add the two highlighted cache operations and do notice in the test call's trace that both are successful. This shows that APIM's policy can use the Redis instance.
image
image

@mikebudzynski, I couldn't add an issue in the Azure API Management repository. So, added the issue here. We are still not able to use policy expression in the rate-limit-by-key policy. I have attached the error screenshot for your reference.

@mikebudzynski, I couldn't add an issue in the Azure API Management repository. So, added the issue here. We are still not able to use policy expression in the rate-limit-by-key policy. I have attached the error screenshot for your reference.

Error: Error in element 'rate-limit-by-key' on line 24, column 10: The 'calls' attribute is invalid - The value '@((int)context.Variables["api.NamedValue.Config.Json.Cache.Duration"])' is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:int' - The string '@((int)context.Variables["api.NamedValue.Config.Json.Cache.Duration"])' is not a valid Int32 value.

image

Originally posted by @dibyaranjanjll in Azure/api-management-developer-portal#1424 (comment)

No byte[] decrypt / encrypt in api-management-policy-snippets/examples /Encrypt data using expressions.policy.xml

Encrypt data using expressions.policy.xml and Decrypt AES Data using policy expressions.xml appear not to work.

 byte[] inBytes = Convert.FromBase64String(context.Request.Body.As<JObject>().SelectToken("encrpText").ToString());
 byte[] decryptedBytes = **inBytes.Decrypt**("Aes", key, IV);**
byte[] gooberBytes = Encoding.UTF8.GetBytes(goober);
byte[] encryptedBytes = gooberBytes**.Encrypt("Aes", key, IV);**

Byte[] doesn't have an encrypt or decrypt method. It also appears that symmetrical encryption isn't possible in API management.

Azure OpenAI + random load balancer policy

Hello,

To setup the Random Load Balancer policy, do I need to name each Azure Open AI Deployed Model the same in each backend?

Example:

  • APIM endpoint: https://apim-<my-org>.azure-api.net
  • Azure OpenAI APIM endpoint: https://apim-<my-org>.azure-api.net/deployments/<deployment-name>/chat/completions?api-version=2023-05-15

The issue is the <deployment-name>. If I setup the Random Load Balancer Policy above, and have two different Azure OpenAI APIM Backends, the URL is different, therefore a random number of requests fail.

Hope this makes sense.

Thank you

APIM manager API policy creation using azuredevops pipeline

Looking for a way to automate the custom policy creation across the scope of api and operations idempoently in Azure API manager.

The pipeline input is as below

stages:
  - template: api-ops-pipeline.yaml
    parameters:
      policyList:
      - name: rate_limit_ip
        scope: api
        apiname: test-policy, test2-policy

      - name: IPfilter
        scope: operation
        ipAddressesFrom: xxxxx
        ipAddressesTo: xxxxxxx
        operationname: getxxx, getyy, getzz

policy.xml template

<policies>
    <inbound>
        <base />
         $(rate-limit-by_ip)
		 $(rate-limit-by_subkey)
		 $(rate-limit-by_DevID)
		 $(rate-limit-by_ip)+$(rate-limit-by_DevID)
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
		 $(rate-limit-by-ip_error)
		 $(rate-limit-by_DevID_error)
		 
    </on-error>
</policies>

As a first task, we have to create the custom initial_policy.xml file in different scenarios as per the policy list provided by the app team and need to generate it in accordance with the scope of the policy (might be specific to api or might be specifically to a single operation in it or multiple operation in it)

We may have the different combination as below and, when the scope is only to operations, it should first check whether the same policy is applied in its parent api or APIM instance level itself.

Combinations

  • rate-limit-by_ip
  • rate-limit-by_subkey
  • rate-limit-by_DevID
  • rate-limit-by_ip+ rate-limit-by_DevID
  • Or any custom combination with on error properties as well

Once the above step is completed, in the above created custom initial_policy.xml , the users inputs parameters are replaced (threshold, time etc..) and final_policy.xml will be created.

Then , finally it can be applied to the scope given, (might be to api/apis or operation/operations)

The pipeline template drafyed as below.

  jobs:
  - job: api
    displayName: 'api policy'
    variables:
    - group: api_policy
    workspace:
      clean: all
    pool:
      name: xxxxxxx
    steps:
    - ${{ each policy in parameters.policyList }}:
      - ${{ if and(eq(policy.name, 'rate_limit_ip'), eq(policy.scope, 'api') ) }}:
        - bash: |      
           apiName=${{ policy.Name }}
           echo "##vso[task.setvariable variable=apiName]$apiName" 
           xxxxxxxxxxxxxxxxx
           xxxxxxxxxxxxxxxxxxxxxxxx
            xxxxxxxxxxxxxxxxxxxxxx          
          name: Resolve_variable  

        - task: qetza.replacetokens.replacetokens-task.replacetokens@3
          displayName: 'create initial xml'
          inputs:
            rootDirectory: '$(System.DefaultWorkingDirectory)/policy'
            targetFiles: initial_policy.xml
            tokenPrefix: '${'
            tokenSuffix: '}$'
            enableTelemetry: false
          continueOnError: true

        - task: qetza.replacetokens.replacetokens-task.replacetokens@3
          displayName: 'create final xml'
          inputs:
            rootDirectory: '$(System.DefaultWorkingDirectory)/policy'
            targetFiles: final_policy.xml
            tokenPrefix: '${'
            tokenSuffix: '}$'
            enableTelemetry: false
          continueOnError: true

Certificate REST API not working

Hi,
I am new to APIM and its policies, I observe that this example is using the Key Vault secret API instead of the certificate API but the Key vault secret API for certificate is deprecated and not allowing to upload certificates in secrets.
I tried using certificate API "https://mykeyvault.vault.azure.net/certificates/mycertificate/?api-version=2016-10-01" but getting error while setting set-variable name="keyVaultCertBase64" .
set-variable
{
"messages": [
{
"message": "Expression evaluation failed.",
"expression": "((IResponse)context.Variables["keyVaultCertResponse"]).Body.As()["value"].ToString()",
"details": "Object reference not set to an instance of an object."
},
"Expression evaluation failed. Object reference not set to an instance of an object.",
"Object reference not set to an instance of an object."
]
}

When I updated line 30 to,
set-variable name="keyVaultCertBase64" value="@(((IResponse)context.Variables["keyVaultCertResponse"]).Body.As()
it returns certificate but then "authentication-certificate body....." fails with not valid base64 string error.
Any help here would be much appreciated.

Thanks,
Pratik

stop global level policy execution at operation level

This is in context of azure api management azure service. New ui changes in azure has changed behavior of policy executions i believe.

i have one policy for jwt-validate set at global level for all apis.

recently i had to add new api which doesnt need jwt validation but certificate authentication.

so in apim i created new api, product and added certificate authentication policy at product level.

when i run my api then jwt policy is also firing. How can i stop it from executing in this case. i removed but it stopped global + product level policy.

i want stop execution of global policy but i want product level policy to execute.

please advise.

How to use set-body template="liquid" to access request body json attribute?

Hi,

The official documentation mentions that set-body can access request body here https://learn.microsoft.com/en-us/azure/api-management/set-body-policy#using-liquid-templates-with-set-body

"The set-body policy can be configured to use the Liquid templating language to transform the body of a request or response. This can be effective if you need to completely reshape the format of your message."

I would like to use set-body to access the request body json and extract specific property, so that It can be use to craft request body for another request.

How to achieve this?

I tried accessing by "body.argument.<property_name>" doesn't work.

Azure Blob SAS Token generated using APIM failing intermittent at Blob

Hi Team,

Good day!!

We have tried to refere the generate shared access token policy snippet code for generating SAS Token using Azure APIM.

During testing we found that SAS Tokens generated are failing to authenticate at storage account and further deep dive we figured out that the SAS Token signatures consisting of the specail charchter '+' is failing to authenticate.

sample Signature for failed case: sig=VBc5wxRxaYtPOVVPtzTq7I5Fsc2uvNU2whpEq790+l2

We have raised an MS Support ticket for the same and they have asked us to raise a issue in the git hub.

Can you please let us know in which cases does this specail symbol + occurs and how to avoid it while generating SAS Code?

Please let us know incsae of any additional queries

Best Regards:
Sai

Certificate retrieved from KeyVault Error

I am working in setting an inbound policy to read the certificate from Key Vault and forward it to the backend under API Management.

When I upload the certificate in APIM itself and use the below line with thumbprint I am able to get a valid response,

<authentication-certificate thumbprint="......" />

When I upload the same certificate in Key Vault and add my policy accordingly. I am able to read the certificate body but when passing it to backed I get the error as per APIM trace "Certificate does not have private key". Below is my APIM policy code for reference :

<cache-lookup-value key="TestCertificate" variable-name="keyVaultCertBase64" />
        <choose>
            <when condition="@(!context.Variables.ContainsKey("keyVaultCertBase64"))">
                <send-request mode="new" response-variable-name="keyVaultCertResponse" timeout="20" ignore-error="false">
                    <set-url>https://testcertvault.vault.azure.net/certificates/TestCertificate/import?api-version=7.1</set-url>
                    <set-method>GET</set-method>
                    <authentication-managed-identity resource="https://vault.azure.net" />
                </send-request>
                <!-- transform response to string and store in cache -->
                <set-variable name="keyVaultCertBase64" value="@(((IResponse)context.Variables["keyVaultCertResponse"]).Body.As<JObject>()["cer"].ToString())" />
                <cache-store-value key="TestCertificate" value="@((string)context.Variables["keyVaultCertBase64"])" duration="3600" />
            </when>
        </choose>
        <authentication-certificate body="@(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]))" />
        <set-backend-service base-url="......." />

I get the same error in track if I update the <set-url> value

<set-url>https://coloclientcert.vault.azure.net/secrets/ColoCertificate/?api-version=7.1</set-url>

Any idea what I am missing.

Need ability to add non-stanrdard URLs to CORS policy

We rely on API Management for all of our needs in Azure and we are migrating Cordova mobile apps to Capcaitor. The CORS URL for Capacaitor is capacitor://localhost and the API Management Gateway will not accept this as valid. Looks like it is only accepting http or https.

Can this be added to the near term roadmap? The hoops we are jumping through to make this work is becoming cumbersome.

Error on trying to Save the inbound rule

The error I'm seeing in the portal is just below.

One or more fields contain incorrect values:
Error in element 'authentication-certificate' on line 62, column 10: The 'body' attribute is not declared.

Please see below the section in question:
<policies> <inbound> .... <!-- check the cache for secret first --> <cache-lookup-value key="mycert" variable-name="keyVaultCertBase64" /> <!-- call Key Vault if secret is not found in the cache --> <choose> <when condition="@(!context.Variables.ContainsKey("keyVaultCertResponse"))"> <send-request mode="new" response-variable-name="keyVaultCertResponse" timeout="20" ignore-error="false"> <set-url>https://certificates-by-subject.vault.azure.net/secrets/cluster-certificate/?api-version=2016-10-01</set-url> <set-method>GET</set-method> <authentication-managed-identity resource="https://key-vault-reader" /> </send-request> <!-- transform response to string and store in cache --> <set-variable name="keyVaultCertBase64" value="@(((IResponse)context.Variables["keyVaultCertResponse"]).Body.As<JObject>()["value"].ToString())" /> <cache-store-value key="mycert" value="@((string)context.Variables["keyVaultCertBase64"])" duration="3600" /> </when> </choose> <authentication-certificate body="@(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]))" /> <base /> </inbound> <backend> <base /> </backend> <outbound> <base /> </outbound> <on-error> <base /> </on-error> </policies>

is there any way to export the effective policy assigned to api and operation level to an xml file?

I tried below option, but its not fetching the effective policy assigned to an api or operation, where as its fetching just the policy assigned to them alone

curl --location 'https://management.azure.com/subscriptions/xxxxxxxxxxxx/resourceGroups/xxxxxxxxx/providers/Microsoft.ApiManagement/service/xxxxxxxxxx/apis/apiname/policies/policy?format=xml&api-version=2022-08-01' --header 'Content-Type: application/json' --header 'Authorization: Bearer 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

Syntax error when processing this sample

<cache-lookup-value key="@(context.Request.MatchedParameters.GetValueOrDefault("place="""))" variable-name="latlong"/>

It seems that this snippet:

context.Request.MatchedParameters.GetValueOrDefault("place=""") // fails with a missing comma.

whilst using it this way:

context.Request.MatchedParameters.GetValueOrDefault("place", "") // works without an issue.

The other parts where there is a variable with var="" under double quotes, the parser doesn't like much.

Allow all IP address

How can we allow all IPs using the policy - "examples/Filter on IP Address when using Application Gateway.policy.xml". Using 0.0.0.0/0 as the IP filter cidr notation does not allow IP address

Match caching key in cache-lookup-value don't work

every time that i call azure redis cache using "cahce-lookup-value" the key has a pre-pended '2_[whatever used value]'

my gateway policy config
image

my azure cache redis - monitor
image

why every call has the prefix '2_'? so I can't match the values ​​because of this

Provide overview of all supported policies

Just a thought but shouldn't we provide a documentation page that lists all policies and give some brief context about them?

Maybe ideal to create examples\README.md which lists them with detailed sections underneath them.
Can introduce it with #15 if you want.

Example

  • Trigger Data Factory Pipeline
  • Call out to an HTTP endpoint and cache the response
  • Add correlation id to inbound request

Trigger Data Factory Pipeline

Policy that allows you to trigger a Data Factory Pipeline and delegating the Azure AD authentication to Azure API Management instead of the user.

Azure Redis Cache Prefixed with 2_

Hi,
From APIM I am unable to access my key-value pairs in Azure Redis Cache, as all the keys are prefixed with _2 when they try to access Redis Cache. Is this bug ?

I also saw another thread that was marked as closed, how I would like understand why is it this way and is there any trust worthy documentation to account for it.

#43

Policy Fragment does not support Authentication policy

Hello,

I am trying to use a policy fragment and has below line in it
<set-variable name="client-id" value="{{ManagedIdentityId}}" /> <authentication-managed-identity resource="https://storage.azure.com/" output-token-variable-name="storage-access-token" client-id="@(context.Variables["client-id"])" />
This does not work giving me error as
authentication-managed-identity (0.009 ms)
{
"message": "Managed service identity is not enabled for this service and authentication-managed-identity policy cannot be used."
}

If i write the policy as below
<authentication-managed-identity resource="https://storage.azure.com/" output-token-variable-name="storage-access-token" client-id="{{ManagedIdentityId}}" />
Does the client-id parameter does not support taking value from context.variables ?

Encryption Policy not working

Hi
I tried running the policy statements in https://github.com/Azure/api-management-policy-snippets/blob/master/examples/Encrypt%20data%20using%20expressions.policy.xml but i get the foll exception

ExpressionValueEvaluationException: Expression evaluation failed. The specified initialization vector (IV) does not match the block size for this algorithm.
Parameter name: iv
at System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(Byte[] key, Byte[] iv)
at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.Context.CryptographyExtensions.Encrypt(Byte[] input, SymmetricAlgorithm alg, Byte[] key, Byte[] iv)
at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.Context.CryptographyExtensions.Encrypt(Byte[] input, String alg, Byte[] key, Byte[] iv)

I am using foll code snippet to generate the key and IV

`
using System;
using System.Security.Cryptography;
public static class AESKeyandIVGenerator
{
public static string GenerateKey()
{
// Generate a 256-bit (32-byte) key
byte[] key = new byte[32];
using var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
rng.GetBytes(key);
Convert.ToBase64String(key);
return BitConverter.ToString(key).Replace("-", "");
}

public static string GenerateIV()
{    
    byte[] iv = new byte[16];
    using var rng = System.Security.Cryptography.RandomNumberGenerator.Create();
    rng.GetBytes(iv);
    Convert.ToBase64String(iv); 
    return BitConverter.ToString(iv).Replace("-", "");
}

static void Main(string[] args)
{
    Console.WriteLine($"Hello! Your 256-bit (32-byte) key is: ");
    Console.WriteLine(GenerateKey());
    Console.WriteLine($"Hello! Your 168-bit (16-byte) IV is: ");
    Console.WriteLine(GenerateIV());        
}

}
`

Sample output

Hello! Your 256-bit (32-byte) key is:
B397B38678D727EF20F65915EC289A34CAAB9107EDB69DC4B26A61FB0B750463
Hello! Your 168-bit (16-byte) IV is:
5A78E054F381A06BA5049914C2604E9A

Can you let me know where i am going wrong?

X509Certificate2 on consumption tier

When loading a certificate in an expression, the following works in developer+ tiers, however not on Consumption tier.

X509Certificate2 certificate = new X509Certificate2(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]), (string)null);

Haven't been able to find in the docs. Am I missing something? Any suggestions greatly appreciated'

About the example Azure Storage Blob CRUD with MSI

Could someone please explain a better examples with CRUD and Msi (deep dive policies) ? What if if I need handle a file of different type ( not json object) ? What about to send this file to blob ? Im trying to get a file from a S3 (via get API) and write this to an blob storage. I can Get data from S3 using send request, otherwise when I try sent that to Blob storage is generated an error because the type of file isn't a pure json object:
https://{{storage}}.blob.core.windows.net/container
POST

2019-07-07


BlockBlob


file

@($"{((IResponse)context.Variables["blobdata"]).Body.As() }")

Here Im trying send "blobdata" because is the variable that contains the file from the first Send-Request ( not presented here). The error I received is following:

"Expression evaluation failed. The message body is not a valid JSON. Unexpected character encountered while parsing value: P. Path '', line 0, position 0.\r\n at Newtonsoft.Json.JsonTextReader.ParseValue()\r\n at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)\r\n at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.AsJObject(Stream stream, Encoding encoding, JsonSerializerSettings settings)\r\n at Microsoft.WindowsAzure.ApiManagement.Proxy.Gateway.MessageBody.As[T](Boolean preserveContent)", "Unexpected character encountered while parsing value: P. Path '', line 0, position 0."

Provide contribution documentation

Provide documentation on how to contribute snippets

It should explain how to :

  • Add a new snippet
  • How it should be documented
  • What the Named Values naming convention is

POST API Validate-Content Policy - Inconsistent errors for missing JSON array beginning and end square brackets

Opening this issue here because the public API Management release notes repository does not allow issues and this is a backend problem and so does not apply to the developer portal.

Bug description

When sending requests to a POST API endpoint, different errors are returned depending upon whether the starting or ending bracket is missing from a sent JSON array. This appears to be an issue with the validate-content validation policy, in that it is not correctly checking for a closing square bracket.

A missing opening square bracket will result in a 400 Bad Request error, which we would expect. However, a missing ending square bracket returns a 500 Internal Server Error. In the second case, although including a notice about invalid JSON, it would seem to imply that the error was with the backend service, rather than with the submitted request, leading to a confusing user experience.

This issue appears to only be present with APIs modified with API Management Policies and not when the same modifications are applied with an Azure Function.

Behavior is present both when testing via the developer portal Operation Details widget Try It panel and via the Azure backend.

Reproduction steps

Using a POST API endpoint that includes the validate-content policy and is modified with XSLT transform policies. The errors appear to occur prior to the XSLT policy being applied.

  1. Send a request using a JSON array missing an opening square bracket but with otherwise valid data
  2. Receive a 400 Bad Request error response

{ "Zip5": "18603" }, { "Zip5": "17815" }, { "Zip5": "17846" }, { "Zip5": "90210" }, { "Zip5": "43823" }]

Screen Shot 2021-09-10 at 9 23 48 AM

  1. Send a request using a JSON array missing a closing square bracket but with otherwise valid data
  2. Receive a 500 Internal Server error response

[{ "Zip5": "18603" }, { "Zip5": "17815" }, { "Zip5": "17846" }, { "Zip5": "90210" }, { "Zip5": "43823" }

Screen Shot 2021-09-10 at 9 24 08 AM

Expected behavior

Requests with formatting/syntax issues result in consistent error responses indicating something is wrong with the request, rather than imply that an issue occurred with the backend service.

Is your portal managed or self-hosted?

Managed

cannot match caching key in cache-lookup-value policy

im doing a version of the simple example in the docs for custom caching using cache-store-value and cache-lookup-value.

i set the key in the store-value section and the key has a pre-pended '2_[whatever ive used for the key]'

so it can never find the value ive stored.

Get thumbprint from certificate retrieved from Keyvault

I am trying to use the policy from the example, Look up Key Vault certificate using Managed Service Identity and call backend.

I am able to get the certificate from the key vault and use if to authenticate to my back end as a client cert. but i am also trying to secure the inbound call on the front end by validating that the caller is sending the same cert.

Using the policy below I am able to retrieve the cert from the keyvault, get the Base64 value out of the cert response. The last step I am missing is how to pull the thumbprint out of that Base64 cert to validate against in the incoming cert thumbprint from context.Request.Certificate.Thumbprint.

The comparison i am struggling with is

<when condition="@(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]) != context.Request.Certificate)">

Full Inbound Policy

<inbound>  
        <base />
        <send-request mode="new" response-variable-name="keyVaultCertResponse" timeout="20" ignore-error="false">
            <set-url>https://MYKEYVAULTNAME.vault.azure.net/secrets/CLIENTCERTTEST/?api-version=2016-10-01</set-url>
            <set-method>GET</set-method>
            <authentication-managed-identity resource="https://vault.azure.net" />
        </send-request>
        <set-variable name="keyVaultCertBase64" value="@(((IResponse)context.Variables["keyVaultCertResponse"]).Body.As<JObject>()["value"].ToString())" />
        <choose>
            <when condition="@(context.Request.Certificate == null)">
                <return-response>
                    <set-status code="403" reason="No Client Certificate Provided to APIM" />
                </return-response>
            </when>
            <when condition="@(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]) != context.Request.Certificate)">
                <return-response>
                    <set-status code="403" reason="Client Certificate Presented to APIM is incorrect" />
                </return-response>
            </when>
        </choose>
        <authentication-certificate body="@(Convert.FromBase64String((string)context.Variables["keyVaultCertBase64"]))" />
    </inbound>

Question: OAuth2 access token from AAD and forward it to the backend

I've been looking at

return "client_id={{clientId}}&scope={{scope}}&client_secret={{clientSecret}}&grant_type=client_credentials";

and had a question to @mike-urnun-msft about caching and checking token expiration time.

Shouldn't OAUTH policy include those to avoid calls to AAD when still valid token could be cached?

Incorrect Sample | Call out to an HTTP endpoint and cache the response.policy.xml

The policy https://github.com/Azure/api-management-policy-snippets/blob/master/examples/Call%20out%20to%20an%20HTTP%20endpoint%20and%20cache%20the%20response.policy.xml is referred to the APIM cache-response document: https://docs.microsoft.com/en-us/azure/api-management/policies/cache-response

When running the policy we can see the error while saving the policy. Please fix the policy so it is reflected correctly in the APIM document.

MicrosoftDocs/azure-docs#95685

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.