Policies in Azure API Management

In order to provide control over interactions with products or APIs in Azure API Management, policies are used. Policies make it possible to change the default behavior of an API in the product, for example, to meet the governance needs of your company or product, and are a series of statements executed sequentially on each request or response of an API. Three demo scenarios will provide a taster of this powerful feature of Azure API Management.

How to use Policies in Azure API Management

Policies are created and managed through the Publisher portal.

The first step in policy creation is to determine at what scope the policy should be applied. Policies can be assigned to all products, individual products, the individual APIs associated with a product, and finally the individual operations associated with an API. This will be demonstrated further.

Click on the Policies option from the sidebar to specify the policy scope and to define the policy using an XSLT-like language:

How to use Policies in Azure API Management

In the Policies screen, we can find existing policies and modify them or create new policies. The drop-down menus provide a way of navigating to the desired policy level.

For example, the policy level defined later is at the operation level, where a Product, API and then Operation has been specified, as indicated in the scope summary section (highlighted):

How to use Policies in Azure API Management

Note that operations with policies defined against them are highlighted with a ■ symbol for easier identification.

To define a policy, we click on the Configure Policy link, which makes the Policy definition editable.

If a policy hasn't yet been created at the required scope, then it will be necessary to create one by clicking on the ADD POLICY link, as illustrated here for the DeleteProduct operation:

How to use Policies in Azure API Management

When we create a policy, we can see a definition created in an XML-like syntax. Clicking on the FULL SCREEN link enables easier editing of the policy where a full screen editable window then becomes available:

How to use Policies in Azure API Management

This screen enables multiple policies to be defined that control how the operation is interacted with and also how the operation behaves, perhaps beyond how the original operation was defined.

The base policy elements are applied in the following order:

  • <inbound>: This specifies policies that should be applied to the inbound message.
  • <backend>: This specifies policies that should be applied to the inbound message before routing to the actual backend service.
  • <outbound>: Policies that should be applied to the outbound message, after calling the backend service, may be specified here.
  • <on-error>: This section may actually be called at any policy stage. If there is an error at any stage processing the request, the remaining steps are skipped and processing enters this policy section for error handling the steps to be applied. Note that this policy element is not present by default when creating a new policy.

Each policy section contains the <base /> element. This element represents the policies inherited from policies specified at a higher scope. For example, because policies may be defined at the global, product, API, and operation level, a global policy could define standard policies that should be applied to all products, APIs, and operations. This saves the chore and maintenance overhead of specifying the same policies multiple times for many products, for example. It is also a useful mechanism to ensure that consistent functionality is applied to all products as a company-wide governance decision. So, in the case of the Sunny Electricals APIs, for example, the following policy has been defined at the API level, for the ProductAPI:

How to use Policies in Azure API Management

Here, we can see that a caching policy has been applied at the ProductApi level.

This policy will be applied to all child operations of the ProductAPI via the <base /> element, which represents all the policies defined at the higher scope. For example, the GetProducts operation has no policies defined except the <base /> element. When the GetProducts operation is called, the response contains caching instructions for the client in the Cache-Control HTTP header, which would only be possible through inheriting the caching policy defined at the higher scoped API level, as shown here:

How to use Policies in Azure API Management

It is possible to specify policies that should execute before/after higher level policies execute by positioning policies before and after the <base /> element.

For policies that appear twice, once in a higher scope level and then at a lower level, the policy at the lower level will be applied and the higher level policy will be skipped. In such a fashion, it is possible to override higher scoped policies.

For example, if we decide that clients should be instructed not to cache calls to the GetProducts operation, we can update the GetProducts policy definition as follows, by redefining a caching policy after the <base /> element, as can be seen here:

How to use Policies in Azure API Management

When we query the GetProducts operation again, the response specifies different caching instructions:

How to use Policies in Azure API Management

We have therefore overridden the base caching policy defined at the API level with a caching policy defined at a lower level.

Since it can be confusing (for humans anyway!) to work with such a hierarchy of abstract policies, the View effective policy for selected scope button can be used to help determine what policy statements will take effect for the policy we are editing.

For example, if we click on the button for the GetProducts operation, we are presented with a view that effectively expands the <base /> element for each policy in the hierarchy and presents all effective policies in the order that they will be executed, in one consolidated view, as shown here:

How to use Policies in Azure API Management

We can work our way through the policies from top to bottom and determine what policies will be fired, remembering that the last policy for a particular policy statement will fire and all other policies of the same type will be skipped.

This view is also useful in that it highlights redundant/unnecessary policies, so it is useful to execute this function from time to time, to check whether redundant policies have been created that may be deleted. In such a way, fewer policies mean that it is easier to determine what policies will fire when presented with this consolidated view in the future. In the example earlier, the <cache-store> statement (Store to cache) is not required (because it is duplicated with the same value for duration), but unfortunately, this cannot be deleted from the GetProducts operation since the <cache-lookup> statement (Get from cache) always requires a matching <cache-store> element.

Working with policies in the Publisher portal

On the right-hand side of the screen, Policy statements provide functions that can be inserted into the policy. They are shortcuts that can be used to insert statements into the policy that can then be subsequently edited, as required. To insert a statement, position the cursor in the appropriate section of the policy and click on the arrow next to the policy.

It is possible to create complex policies to meet your needs by inserting multiple policy statements and conditional logic, for example.

What are the different policies available in the Publisher portal?

The table here summarizes the different policies available. Note that the arrow icon next to the policy statements will appear disabled, if they cannot be applied at the current scope or at the message stage (inbound or outbound).

Category

Policy

Description

Access Restriction

Check HTTP header

Enforce HTTP header existence/value.

Limit call rate

Limit the number of calls allowed by time and frequency by subscription or key.

Restrict caller IPs

Allow/deny connections by IP address or range.

Set usage quota

Specify the usage by maximum allowable calls and/or data usage by subscription or key.

Validate JWT

Enforce JWT (JSON web token) existence/validity.

Advanced

Control flow

Conditionally, apply policies based on the predicate evaluation.

Forward request

Forward to backend service.

Log to EventHub

Send messages to EventHub.

Return response

Returns directly to the user, aborting execution.

Send one way request

One way request sent to the specified URL without waiting for a response.

Send request

Sends a request to the specified URL.

Set request method

Specify the HTTP verb for a request.

Set status

Set the HTTP status code to the indicated value.

Set variable

Write a value to a variable for access later.

Wait

Waits for enclosed Send, cache retrieval, or control flow to complete before allowing execution to proceed.

Authentication

Authenticate with Basic

Authenticate with a backend service using HTTP basic.

Authenticate with client certificate

Authenticate with a backend service using the specified client certificate.

Caching

Get from cache

Do a cache lookup and use the valid cached response.

Store to cache

Store the response in the cache.

Get value from cache

Obtain an item from the cache by the specified key.

Store value in cache

Store in the cache by the specified key.

Cross domain

Allow cross domain calls

Allows requests from other domains, enabling access for Adobe Flash and Silverlight browser-based clients.

CORS (cross origin resource sharing)

Permits browser-based calls from other domains to an API or operation.

JSONP (JSON with padding)

Permits browser-based calls from other domains to an API or operation, from JavaScript.

Transformation

Convert JSON to XML

Translates request or response messages from JSON to XML.

Covert XML to JSON

Translates request or response messages from XML to JSON.

Find and replace string in body

Replaces the specified string in the request or response body with a different string.

Mask URLs in content

Use to modify URLs in request or response messages to or from a masked URL.

Set backend service

Sets the backend service for an incoming message.

Set body

Sets the body content of request or response messages.

Set HTTP header

Specify a HTTP header value in the request or response message that will insert a new header or overwrite a pre-existing header value.

Set query string parameter

Modifies the request query string parameter.

Rewrite URL

Use to rewrite a URL to the format expected by the backend service.

The following sections demonstrate three scenarios where policies have been applied to the Sunny Electricals ProductAPI.

Basic Scenario #1 – Throttle Requests Using a Rate Limit Policy

In this scenario, Sunny Electricals have decided to restrict the number of requests to the ProductAPI to ensure that all developers developing against the API can have access for testing purposes. This is to prevent the API from becoming overloaded and subsequently unable to service requests to some developers.

To achieve this, the API scope is specified, the FULL SCREEN option is selected, and the Configure Policy link is clicked, enables the editing of the API level policy.

The cursor is placed on a new line in the <inbound> policy element and the arrow by the Limit call rate per key policy statement is selected, to insert a <rate-limit-by-key /> policy element that can then be populated with real data, overriding the dummy data that is provided by default, as shown here.

Basic Scenario #1 – Throttle Requests Using a Rate Limit Policy

Here, we can see that the rate limit policy will be applied after the product policy has been applied, indicated by the <base /> element (so overriding any rate limit specified in it), that the number of connections will be restricted to 10, after which the service will prevent further connections for that subscription key (specified in the HTTP header) for 60 seconds.

We can test this out using the Developer Portal by repeatedly calling the GetProducts operation. The following response will be received when the rate limit has been reached, proving that the inbound policy is in effect:

Basic Scenario #1 – Throttle Requests Using a Rate Limit Policy

Basic Scenario #2 – Rewrite the public facing URI for the GetProducts API operation

This scenario demonstrates the <rewrite-uri /> policy. In this simple example, a new version of the GetProducts operation has been written, and it is now required that all requests to look up a product are now obtained from a version 2 of the base API. This is achieved using the inbound policy specified here:

Basic Scenario #2 – Rewrite the public facing URI for the GetProducts API operation

As can be observed in the screenshot earlier, the policy will rewrite the URL to include v2 (indicating Version 2). So, for example, a public request to the URL https://sunnyapimanagement.azure-api.net/api/Products/1 will be rewritten to https://sunnyapimanagement.azure-api.net/api/v2/Products/1. This will be transparent to the client, who need never know that their request is routed to a version 2 of the API operation.

Getting slightly more advanced – Modify default API behavior using conditional statements

Sunny Electrical has decided to implement monitoring to their ProductAPI whereby they test end-to-end connectivity to the backend API by sending a heartbeat-type message to confirm service availability.

However, they wish to retain caching for normal operation.

In order to skip the cache for heartbeat messages, cache lookup is conditionally applied depending on the value of a custom HTTP header defined as X-MessageType. If the value for the X-MessageType header is heartbeat, cache lookup is skipped and data is instead obtained from a direct call to the backend API. The following conditional policy is added to the policy as follows:

Getting slightly more advanced – Modify default API behavior using conditional statements

Here, we can see how conditional logic has been applied to the <inbound> and <outbound> policy elements using the XSLT syntax combined with C# 6.0 code statements. The code checks the value of the custom X-MessageType header, and if it matches the string literal "heartbeat", the cache lookup policy is missed and instead a direct call to the product API is made.

The <outbound> policy also modifies the HTTP status reason code, to indicate to the user that this was a heartbeat-type message.

We can test this policy using the Developer portal by specifying a header in the request message as follows, by clicking on the Add header link and specifying the custom header details:

Getting slightly more advanced – Modify default API behavior using conditional statements

Now that the HTTP request includes our custom HTTP header, we can send the message, and the response should result from directly calling the ProductAPI, providing a mechanism to test service connectivity end-to-end, and bypassing the APIM cache.

The HTTP response message also includes the custom HTTP status reason code:

Getting slightly more advanced – Modify default API behavior using conditional statements

We can download a trace file to also check our policy execution. The trace URL is indicated in the Ocp-Apim-Trace-Location HTTP header in the APIM response message, as shown earlier. Using a tool such as Fiddler, we can execute HTTP GET on the URL, and this will return a trace file in JSON format. We could also cut and paste the URL into a browser window, but Fiddler provides easier visualization of the JSON.

Trace execution is toggled via the Ocp-Apim-Trace HTTP header in the request message. If it is set to true, trace data will be available.

If we compare the trace files with and without the X-MessageType header set, we can see that heartbeat messages skip the cache lookup policy whilst those without the header do include execution of the cache lookup policy. The example here shows the trace for a non-heartbeat message, where the trace indicates that the inbound cache lookup policy has been hit:

Getting slightly more advanced – Modify default API behavior using conditional statements

Also, it is apparent that heartbeat messages are skipping cache lookup because they take longer to execute than cached responses (cached responses are approximately 10 times faster than noncached responses).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset