Azure API management - custom domain specific APIs? - azure

I could successfully add the custom domain to the Azure API management and access the APIs.
I do understand that Azure API management supports multiple custom domains.
However all the APIs are accessible across the custom domains.
Is there any way to limit the APIs per custom domain? Eg: API1 will be available only for the domainX while API2 is accessible for domainY.

You could use an API level or Product level policy to return an Unauthorized status code when the Uri of the incoming call is on the wrong domain:
<policies>
<inbound>
<base />
<choose>
<when condition="#(context.Request.OriginalUrl.Host != "domainX")">
<return-response>
<set-status code="401" reason="Unauthorized"/>
</return-response>
</when>
</choose>
</inbound>
</policies>

Related

Can I call different backend on Azure API Management

I am trying to achieve that, when I call an APIM Endpoint based on the request headers It should different endpoint. for e.g when user call https://test.azure-api.net/testsvc-dev/api/test APIM should be able to send the request to https://testappv1:80/test or https://testappv2:80. right now I can see in the serviceURL, I can add only one. Is there any policy that I can use to do these kind of operations.
little more context: I am trying to access two different version of API on a single call. Instead of caller choosing which one to call,I am trying to make the APIM to decide based on the user.
You are probably looking for the set-backend-service policy.
Here an example from the Microsoft docs that changes the backend service based on a query parameter:
<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>
Certainly, you could adopt the sample and query for the desired headers ;-)

How to setup 405 Method Not Allowed for each of the methods in APIs using azure API Management

In azure API Management how to setup the 405 (Method not allowed) policy. I am using azure API management APIs and adding different policies like jwt validation, IP filtering, rate limit and all. But I couldn't find a way for add the 405 method not allowed in APIM. I want to setup this for each of the methods. That means I want to block the incoming unrecognized method requests from APIM. (eg: Get instead of POST (Throws 405 method not allowed from APIM). Currently APIM passes the wrong method to backend and it returns the 404 from the application. Anyone know how we can block the wrong request from APIM side and returns 405 instead of passing it to backend and returns 404?.
You could use a Control Flow policy along with the Context Variable on the Inbound policy of each Method to intercept any requests that don't match the defined http method and then use a Set Status policy to return a 405. So for a GET method something along the lines of:
<policies>
<inbound>
<choose>
<when condition="#(context.Request.Method.ToString() != "GET")">
<return-response>
<set-status code="405" reason="No Content" />
</return-response>
</when>
</choose>
<base />
</inbound>
... rest of policies
</policies>
If you've got multiple methods with the same path you might need to apply this at the API level rather than the Method level and make the condition equals methods not in use rather than not equal to method in use
To set this at the API level and check against a collection of methods not in use create a policy along the lines of:
<policies>
<inbound>
<choose>
<when condition="#{
ICollection<string> disallowedMethods = new List<string>() { "POST", "PUT" };
return disallowedMethods.Contains(context.Request.Method.ToString());
}">
<return-response>
<set-status code="405" reason="No Content" />
</return-response>
</when>
</choose>
<base />
</inbound>
... rest of policies
</policies>
The http methods not in use in this example are POST and PUT but you can change the list to whatever applies in your use case.

Forward requests to regional API based on a specific JWT claim

Is it possible to forward requests to regional API based on a specific JWT claim?
The platform I'm working on has one API per region, and our customers are required to know it in order to build the base request URL - e.g.: https://{region}.service.com
Unfortunately, the only reliable way to try and figure out which regional api to call automatically from Azure APIM (e.g.: calling a single endpoint at https://api.service.com), in our scenario, would be by analyzing a claim that always comes with the bearer token (which we already do at the APIM level.)
Has anybody had the need to do it this way? Thanks in advance!
APIM policy expressions along with "choose" policy allow you to create arbitrary processing logic: https://learn.microsoft.com/en-us/azure/api-management/api-management-policy-expressions.
Access to JWT is available as
context.Request.Headers.GetValueOrDefault("Authorization").AsJwt()
It returns Jwt object (look for it's properties on the same page above).
All this combined with "set-backend-service" policy should be sufficient to do the job.
Vitaly's answer was the key to figuring this one out. Here is the complete answer, in case anybody is looking for the same thing.
<policies>
<inbound>
<!-- Extract Token from Authorization header parameter -->
<set-variable name="token" value="#(context.Request.Headers.GetValueOrDefault("Authorization",string.Empty).Split(' ').Last().AsJwt())" />
<choose>
<when condition="#(context.Variables["token"] != null)">
<set-variable name="api_uri" value="#(((Jwt)context.Variables["token"]).Claims.GetValueOrDefault("api_uri", string.Empty))" />
<choose>
<when condition="#(context.Variables["api_uri"] != string.Empty)">
<set-backend-service base-url="#((string)context.Variables["api_uri"])" />
</when>
<otherwise />
</choose>
</when>
<otherwise />
</choose>
<base />
</inbound>
</policies>

How can you use Azure API Management policy to load balance calls to a backend service?

How can you use policy to load balance calls to a pair of backend services? (in this case a pair of Logic Apps in different regions)
I've read through the API Management policies and can see something around the control flow but I can't work out how to (a) test the back-end service is available, and then (b) change the call to the backup service if the primary is unavailable
<backend>
<forward-request/>
</backend>
One more way to achieve this could be that you can use the retry policy with set backend service or send-request
with something like
<backend>
<retry condition="#(context.Response.StatusCode == 400 || context.Response.StatusCode >= 500)" count="10" interval="10" max-interval="100" delta="10" first-fast-retry="false">
<choose>
<when condition="#(context.Response != null && (context.Response.StatusCode == 400 || context.Response.StatusCode >= 500)">
<set-backend-service base-url="http://echoapibackup.cloudapp.net/api" />
</when>
<otherwise>
<set-backend-service base-url="http://echoapi.cloudapp.net/api" />
</otherwise>
</choose>
<forward-request />
</retry>
</backend>
This will in case your primary backend returns an error, will keep retrying on your backup backend.
Look into using send-request policy. With it (and wait policy) you could make parallel calls to a couple of web services and return result from one that completes first. That would mean that you need to skip forward-request altogether as you'll be getting result data from these policies.
Or you could use send-request to test if certain backend is available and then use set-backend-service and/or rewrite-uri policies to change destination backend. In that case you'll be keeping forward-request.

Redirect policy in Azure API Management

Does Azure API Management (Azure APIM) provide any way to redirect urls, in order to replicate Apigee RedirectToLoginPage functionality
You can do it with a policy set at the global (All APIs) scope.
<choose>
<when condition="#(!context.Request.OriginalUrl.Host.Contains("redirect.com"))">
<return-response>
<set-status code="303" reason="See Other" />
<set-header name="Location" exists-action="override">
<value>#("https://redirect.com/" + context.Request.OriginalUrl.Path + context.Request.OriginalUrl.QueryString)</value>
</set-header>
</return-response>
</when>
</choose>
At the time of writing this isn't supported at Azure APIM level. Since I was using IdentityServer for Oauth2 security, I accomplished this by writing an owin/katana authentication middleware. Anders Abel has a great post about it.

Resources