I am trying to create a policy in APIM which fetches the product for the subscription-key passed in the header. I need to get that product name and do set-header with that name for the backend service. Is it possible to achieve it through APIM Policies ?
First, we added two more subscription scopes: all APIs and a single API. The scope of subscriptions is no longer limited to an API product. It's now possible to create keys that grant access to an API, or all APIs within an API Management instance, without needing to create a product and add the APIs to it first. Also, each API Management instance now comes with an immutable, all-APIs subscription. This subscription makes it easier and more straightforward to test and debug APIs within the test console.
You can get the Product Name with #(context.Product.Name).
<inbound>
<base />
<set-variable name="aaa" value="#(context.Product.Name)" />
<set-body template="liquid">
{
"success": true,
"var1": {{context.Variables["aaa"]}}
}
</set-body>
</inbound>
In test, set the product name as Starter and you will get the snapshot as below.
Related
I'm trying to get my backend API to authenticate that requests are from Azure APIM using managed identities, previously this was done with certificate authentication but for various reasons I'm looking to change that.
When I make requests to the APIM, I get the following error in application insights.
Managed service identity must be configured to use authentication-token policy.
In the backend I'm using Owin's Windows Azure Active Directory Bearer Authentication.
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = "https://tennant.co.uk/AzureADDAuth",
TokenValidationParameters = new TokenValidationParameters
{
ValidAudience = "11111111-1111-1111-1111-111111111111"
},
});
In the APIM the inbound policy is as follows
<authentication-managed-identity resource="https://tennant.co.uk/AzureAADAuth" client-id="11111111-1111-1111-1111-111111111111" output-token-variable-name="msi-access-token" ignore-error="false" />
<set-header name="Authorization" exists-action="override">
<value>#("Bearer " + (string)context.Variables["msi-access-token"])</value>
</set-header>
I find the error message quite vague though and I've not found any help online so I'm not sure what I need to do to set up this configuration. I've looked through several docs and blog posts on this topic and can't find anything about what to change in the Azure Active Directory. If you could point me in the right direct I'd appreciate it.
I fixed this by removing the client id from the APIM inbound policy.
I'll be so gratefull if you can help me with the following question: I´m resticting the access to use an API in APIM using groups, but I want to restrict even its operations for example: I have an API in APIM with the following operations:
OperationA
OperationB
OperationC
And the following groups of users:
Group1
Group2
Group3
so the idea is to give access to the groups according some business rules for instance:
Group1 (OperationA, OperationB)
Group2 (OperationA)
Group2 (OperationA,OperationB,OperationC).
Is there a way to implement this behavior? Thank you so much
For this requirement, you can use validate-jwt policy at the operation level.
First, you need to include groups claim in your token as instructed here. You just need to modify the "groupMembershipClaims" field in application manifest:
"groupMembershipClaims": "SecurityGroup"
Then the token will contain the Ids of the groups that the user belongs to like below:
{
"groups": ["1ce9c55a-9826-4e32-871c-a8488144bb32"]
}
Then use validate-jwt policy in your APIM to check if the field groups contains the group(group1, group2 or group3) id. If yes, then do the backend api. If no, you can set a 403 forbidden response in policy like below:
<return-response>
<set-status code="403" reason="Forbidden" />
</return-response>
I am using Azure API Management as front end for my Logic App. The "subscription required" setting needs to be enabled as we do need the protection. However, we must send the key via query parameter because our calling application only supports GET, not POST.
So my API call was sent to Azure using the format of https://my.azure-api.net/myapi/manual/paths/invoke?subscription-key=mykey
Now in Azure API setting I did create a policy set to delete action on the "subscription-key" query parameter, but here's the problem:
Even though the parameter is removed from the request body into Logic App, upon digging into the "RAW" outputs in Logic App where it shows various headers, we can see the subscription-key in these two headers:
"X-WAWS-Unencoded-URL": "/myapi/manual/paths/invoke?subscription-key=xxx
"X-Original-URL": /myapi/manual/paths/invoke?subscription-key=xxx
In other words, the full original query URL was made available to Logic App before the parameter was removed. This exposes the API subscription key to the Logic App.
Is there any workaround for this?
Ah I see now that those headers were actually sent automatically by Azure API Management to the backend Logic App API, so all I had to do was to set header policies to remove them in addition to the query parameter policy.
<set-query-parameter name="subscription-key" exists-action="delete" />
<set-header name="X-WAWS-Unencoded-URL" exists-action="delete" />
<set-header name="X-Original-URL" exists-action="delete" />
This takes care of it.
Can we have API management end point exposed with out the subscription key sent as a part of headers?
It is possible to achieve this, you can do so via the product the API is associated with.
In the Publisher Portal go to the products menu and select the product the API is associated with (or even set up a new product just for the usage without the subscription key). Then select the settings tab and uncheck the Require Subscription checkbox and then save the settings.
Updated following comment by #sdementen
Please be aware in doing so, you will loose all metrics associated with the different users and any other functions that you may wish to apply differently to different consumers.
There is a very simple way to do this via the API Management interface.
On the APIs page, select your API, then click on the "Settings" tab. Scroll down to the "Subscription" section and uncheck the "Subscription required" option.
You will now be able to call your api without providing the subscription key either in the headers or as part of the querystring.
Another option is to send the subscription key in the URL, if you go to the developer portal and download the Swagger document of your API, you will see this:
{
"name": "subscription-key",
"in": "query",
"description": "subscription key in url",
"type": "string"
},
{
"name": "Ocp-Apim-Subscription-Key",
"in": "header",
"description": "subscription key in header",
"type": "string"
}
API management also accepts a subscription key in the querystring.
I tried creating a new product that does not require a subscription. I updated one of my APIs such that it was only associated with this new product. When I tested it, I got an 400 level error (I think a 401) that complained about the request not having a subscription id.
I contacted Azure support about this, and found out that it is a known bug. Copy/pasting the response here:
While investigating your issue, it seems that your APIM service has
encountered a known bug. Due to this bug, turning a product from
closed (requiring a subscription) to open (does not require a
subscription) does not always properly take effect. However, this can
easily be fixed by rebooting the VM the APIM service is hosted on. You
can do this by going to the VNET blade on the left side navigation
menu under the APIM and pressing the "Apply network configuration"
button at the top. This reboots the Dev SKU VM and should put you in
the proper position to not need subscription keys.
Upon rebooting, the APIM should be down for about 5 minutes, with 15
minutes being the maximum it should take to reset the VNET. When the
APIM comes back up, it may need an additional, small amount of time to
settle itself(maybe 5-10 minutes) then it should be good to go as
desired.
Microsoft has added a new scope for ocip-subscription-key in azure APIM which bypass the product scope. We can use this key in test console.
https://learn.microsoft.com/en-us/azure/api-management/api-management-subscriptions
Now problem is there is no way I can remove this key. If I send request from postman with this key in header my API bypass the Authorization header which is set at product level and calls my API.
I have restricted this header in my API with below code
<check-header name="Authorization" failed-check-httpcode="401" failed-check-error-message="Not authorized" ignore-case="false" />
<choose>
<when condition="#{
string[] value;
if (context.Request.Headers.TryGetValue("Ocp-Apim-Subscription-Key", out value))
{
if(value != null && value.Length > 0)
{
return true;
}
}
return false;
}">
<return-response response-variable-name="response">
<set-status code="401" reason="Unauthorized" />
<set-body>
{"statusCode": 401,"message": "Subscription key not allowed"}
</set-body>
</return-response>
</when>
</choose>
Here 1st I am checking that request should contain Authorization header. And after that I am sending error if request contains ocip-subscription-key.
Is there any better way I can stop my request sending global ocip-subscription-key
Thanks
I want to record the timings for the backend web service being fronted by the API Management service. We front a few 3rd party services so the only way we can get performance data is to log the backend request before and after. My plan was to utilise the base policy (All APIs / All Operations) like this
<backend>
<!-- log start of request -->
<forward-request />
<!-- log end of request -->
</backend>
But trying this I get;
Error in element 'backend' on line XX, column XX: backend section
allows only one policy to be specified
Can you have any policy expressions in the backend element?
backend section is very limited in what policies are allowed there. Your best option would be to do your logging last thing in inbound and first thing in outbound. You can control what policy is executed first by moving "base" tag to a desired position, it effectively controls when (and if) upper level policies are executed.
You can use Log to EventHub in this case to log whatever you want for a given request (which has Id you can use as correlation id).