API Manager: Use re-written URI in Send-Request method - azure-api-management

I currently have two resource groups: A and B. Resource group A contain my APIM and one LogicApp. However, I also need to call upon a LogicApp in resource group B.
To do this, I'm trying to manually send a HTTP call to the LogicApp in the other resource group through the APIM Policy.
I've been stuck on this the entire day thus far.
My current policy code looks like this:
<policies>
<inbound>
<base />
<!-- Load query parameter -->
<set-query-parameter name="id" exists-action="override">
<value>#(context.Request.MatchedParameters["id"])</value>
</set-query-parameter>
<!-- Insert the ID into the URL by rewriting it -->
<rewrite-uri template="https://<logicAppAddress>/triggers/manual/paths/invoke/{id}?<otherPartofUrl>" copy-unmatched-params="true" />
<send-request ignore-error="false" timeout="20" response-variable-name="MasterKeyResponse" mode="new">
<!-- How do I get the re-written URL here? -->
<set-url>#( context.Request.Url.Path )</set-url>
<set-method>GET</set-method>
</send-request>
</inbound>
<backend>
<base />
</backend>
<outbound>
<base />
</outbound>
<on-error>
<base />
</on-error>
The "id" variable gets put into the address correctly, which is great, seeing as the LogicApp calls upon a CosmosDB to retrieve data and then manipulates it.
However, for some reason, I can't seem to get this rewritten URL into the <set-url> section of the <send-request> function.
I really apologize if this is a stupid question, I'm currently interning and this is the first time working with Azure APIM, so it's all relatively new to me. I couldn't find an answer to this on Stackoverflow.
Or is there a better way to do this? Perhaps I'm overlooking something.
Thank you very much for your help in advance and have a nice day.

Solved! For anyone struggling with this later on, this post helped me solve it:
Azure APIM pass through request querystring to backend completely

Related

Azure API Management: cache-store not honoring duration

In Azure APIM, I have an API that queries a SQL table. I created a cache policy for the API to expire after 300 sec. I then created a script to invoke the API every 10 min, and traced the API response and SQL Server db.
For almost an hour, all calls to the API were cache hits - only two cache misses were recorded in App Insights (the first call and last call at the +50 min mark), and only two sql calls were recorded in my sql profiler trace (the first and last call).
I was expecting to see a cache-miss almost every time, but did not. Am I misunderstanding cache-store?
Here is the policy definition:
<policies>
<inbound>
<base />
<cache-lookup vary-by-developer="false" vary-by-developer-groups="false" must-revalidate="true" downstream-caching-type="none" caching-type="internal">
<vary-by-query-parameter>xxxxx</vary-by-query-parameter>
</cache-lookup>
</inbound>
<backend>
<base />
</backend>
<outbound>
<cache-store duration="300" />
<base />
</outbound>
<on-error>
<base />
</on-error>
</policies>
Can you please try the modified outbound policy:
<cache-store duration="10" cache-response="true" />
Store to cache
cache-response:
Set to true to cache the current HTTP response. If the attribute is omitted or set to false, only HTTP responses with the status code 200 OK are cached.
This does also mean, you have to check your current response codes 200/400/404/500/...
Maybe there was most of the time a 404 response, which was not cached.

Create Custom policy in Azure API Management

I want to validate custom claims which are part of JWT token. Token has custom user claims, application claims and other details.
For user claims, I want to have custom policy/block like
<validate-logintype> {validation logic in this block} </validation-logintype>
For application claims, custom policy like
<request-from> {validation logic} </request-from>
Include the above blocks in actual API policy
User API:
<policy>
<inbound>
<validate-logintype>
<base />
</inbound>
</policy>
Can someone please help how this can be implemented.
something like this?
<policies>
<inbound>
<base />
<set-header id="apim-generated-policy" name="Ocp-Apim-Subscription-Key" exists-action="delete" />
<validate-jwt header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">
<openid-config url="https://login.microsoftonline.com/<yourtenant>/.well-known/openid-configuration" />
<audiences>
<audience>{{claim1}}</audience>
</audiences>
</validate-jwt>
</inbound>

CORS and Custom Headers not set in Azure API Management

I'm trying to set up an Azure API but no matter what I do, the CORS headers are not added to my response. I've also tried just adding a random header and that isn't working either.
I've seen multiple other posts on S/O and elsewhere and as near as I can tell, my policies are correct. Is there something else I need to do? Below is the calculated effective policy for an operation. This is a simple GET, though I've also tried with a POST with the same results. When I call the API from Postman and specify my SubscriptionKey in the header, I get back the 201 response specified in my mock policy, but no additional headers. Fiddler confirms that the response does not contain either the CORS or my X-WTF header.
When I call the API from the Test tab in APIM, it also succeeds with the 201 but no additional headers.
<policies>
<inbound>
<!-- base: Begin Api scope -->
<cors>
<allowed-origins>
<origin>*</origin>
</allowed-origins>
<allowed-methods>
<method>*</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
<!-- base: End Api scope -->
<mock-response status-code="201" content-type="application/json" />
</inbound>
<backend>
<!-- base: Begin Api scope -->
<!-- base: Begin Product scope -->
<!-- base: Begin Global scope -->
<forward-request />
<!-- base: End Global scope -->
<!-- base: End Product scope -->
<!-- base: End Api scope -->
</backend>
<outbound>
<!-- base: Begin Api scope -->
<set-header name="X-WTF" exists-action="override">
<value>147852</value>
</set-header>
<!-- base: End Api scope -->
</outbound>
<on-error />
I believe the cause for that behavior is the mock-response policy. As mentioned in the documentation, this command "aborts normal pipeline execution and returns a mocked response to the caller", so you seem to end up receiving the exact mocked response, as no other policies are processed.
You can, however, enrich your mocked response either by adding parameters to your mocked-response policy or by using the return-response policy.
This blog post, despite being from 2017, presents these options nicely :)

Azure API Management Restrict multiple caller IP Address API in API endpoint level

I wanted to restrict some IP's in Azure APIM policy level.
I went thro below links;
https://learn.microsoft.com/en-us/azure/api-management/api-management-access-restriction-policies#RestrictCallerIPs
Azure API Management Restrict multiple caller IP Address
But not sure how can I do this to API end-point level using policy scope
I have below code in the policy.xml:
<policies>
<inbound>
<base />
<!-- statements to be applied to the request go here -->
<authentication-certificate thumbprint="#((string)context.Variables["ClientCertificateThumbprint"])" />
<rate-limit-by-key calls="100" renewal-period="60" counter-key="#(context.Request.Headers.GetValueOrDefault("Ocp-Apim-Subscription-Key"))" />
<cors>
<allowed-origins>
<origin>*</origin>
</allowed-origins>
<allowed-methods preflight-result-max-age="600">
<method>*</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
<ip-filter action="allow">
<address>55.11.187.20</address>
<address-range from="186.168.95.0" to="186.168.95.20" />
</ip-filter>
</inbound>
<backend>
<base />
<!-- statements to be applied before the request is forwarded to
the backend service go here -->
</backend>
<outbound>
<base />
<!-- statements to be applied to the response go here -->
</outbound>
<on-error>
<base />
<!-- statements to be applied if there is an error condition go here -->
</on-error>
</policies
>
Using control flow in Advanced policies you can change the scope to API endpoint level (operation) to restrict IP addresses as below
<choose>
<when condition="#(context.Operation.Id.Equals("StatusGet"))">
<ip-filter action="allow">
<address>55.11.187.20</address>
<address-range from="186.168.95.0" to="186.168.95.20" />
</ip-filter>
</when>
</choose>
</inbound>
Refer: https://learn.microsoft.com/en-us/azure/api-management/api-management-advanced-policies
Navigate to Azure portal, your APIM service, APIs.
Click API you want to apply IP filter to
In the "Inbound processing" section click "Add policy" and select IP filter.

Azure API Management: Doing a global policy for set-backend-service results in scope error

So globally on my API service, I always wish to set the backend service URL based on certain calling regions.
According to this MSDN library article, using the set-backend-service policy sounds perfect for this, and it's a global policy according to its policy scope at the bottom.
However, even posting their exact example...
<policies>
<inbound>
<choose>
<when condition="#(context.Request.Url.Query.GetValueOrDefault("version") == "2013-05")">
<set-backend-service base-url="http://contoso.com/api/8.2/" />
</when>
<when condition="#(context.Request.Url.Query.GetValueOrDefault("version") == "2014-03")">
<set-backend-service base-url="http://contoso.com/api/9.1/" />
</when>
</choose>
</inbound>
....results in an error:
"Error in element 'set-backend-service' on line 0, column 0: Policy is
not allowed in the specified scope"
I can't figure out how to make it any simpler of a situation to troubleshoot. I even removed the conditional statement and just left the policy alone and it still shows the scope error.
I know this global scope works okay, since I was able to put in an xml-to-json policy as a temporary test and save successfully.
I would figure someone ran into this issue already, as this must be a common use case for this policy. Otherwise, I think the MSDN article is out of date, unless anyone here can see any issues.
Here's my policy scope for global:
Change the quotes to single quotes where "version" is. I just ran the following no problem:
<policies>
<inbound>
<choose>
<when condition="#(context.Request.Url.Query.GetValueOrDefault('version') == '2013-05')">
<set-backend-service base-url="http://contoso.com/api/8.2/" />
</when>
<when condition="#(context.Request.Url.Query.GetValueOrDefault('version') == '2014-03')">
<set-backend-service base-url="http://contoso.com/api/9.1/" />
</when>
</choose>
<base />
</inbound>
<outbound>
<base />
</outbound>
</policies>