Contact Free trial Login

Custom Policy Development Reference

The Mule 4 engine is more powerful than the Mule 3 engine when building custom policies due to the heavy use of Mule 4’s architecture and XML schema language.

We use Maven to build and deploy Mule 4 policies. Policies consist of two files:

  1. A deployable JAR file that contains the policy implementation.

  2. A YAML Configuration File, where the policy parameters and metadata are defined.

To package a policy in Maven, the development project must be composed of the following files

  • An XML template

    It contains the implementation of the policy using Mule’s XML schema language.

  • A YAML file

    It defines the configurable parameters of the policy. Anypoint API Manager uses this file to render the UI to display inputs for the policy.

  • The template’s pom.xml file

    It defines policy dependencies. The packaging type needs to be mule-policy. The pom.xml file may define any other Maven plugin that helps to manage the development lifecycle of the Maven project.

  • Resources

    Optional files that the policy depends on, such as certificates and configuration properties files.

  • The mule-artifact.json descriptor

    Policies cannot export resources nor packages such as Java classes.

Basic XML structure

Below is an example of the basic structure of a policy configuration:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:http-policy="http://www.mulesoft.org/schema/mule/http-policy">

  <http-policy:proxy name="policy-template">  (1)
     <http-policy:source>  (2)(3)
         <http-policy:execute-next/> (4)(5)
     </http-policy:source>
  </http-policy:proxy>
</mule>
1 The definition of a policy starts with the http-policy:proxy element with a name argument. The http-policy:proxy element must contain http-policy:source or a http-policy:operation element. In this example, http-policy:source is used.
2 The http-policy:source block contains the actual instructions to execute, relative to the Mule flow the policy is configured to handle. The http-policy:source block can inject instructions before an HTTP Listener event fires at the start of a flow, and inject instructions after the flow completes.
3 Any Mule Event operation that is defined before the execute-next element will be executed before the start of a flow with an HTTP Listener.
4 The http-policy:execute-next element is required to continue the Mule Event processing. The http-policy:execute-next element can trigger other policies or the application flow. Any policy can stop the Mule Event processing chain by not executing http-policy:execute-next.
5 Mule Event operations defined after the http-policy:execute-next element will be executed after the flow completes. These Mule Event processors will be able to process the Mule Event returned from the flow.

Understanding execution order

Consider the case where a Mule application contains two policies, A and B.

Policy A has order 1 and Policy B has order 2.

Policy A is defined by the following configuration:

  <http-policy:proxy name="policy-A">
     <http-policy:source>
          <A1 />
         <http-policy:execute-next/>
          <A2 />
     </http-policy:source>
  </http-policy:proxy>

And policy B config is:

  <http-policy:proxy name="policy-B">
     <http-policy:source>
          <B1 />
         <http-policy:execute-next/>
          <B2 />
     </http-policy:source>
  </http-policy:proxy>

A flow is defined as:

  <flow name="flow">
     <http:listener />
     <F1/>
  </flow>

When an HTTP Request arrives at the Mule application’s endpoint, the execution order follows the diagram below:

<A1> → <B1> → <F1> → <B2> → <A2>

The policy with the lower order executes first. The flow will always execute in the middle of the policy operations.

With this model, the Mule Event processing chain can be controlled with the presence or absence of the http-policy:execute-next element.

For example, by placing the http-policy:execute-next element inside a choice element, the next Mule Event execution can continue or stop, depending on the choice condition.

In the example below, the flow will only execute when the incoming request has a header named myHeader and its value is someValue. A message is logged if the incoming request does not satisfy the constraint.

  <http-policy:proxy name="policy">
     <http-policy:source>
        <choice>
           <when expression="#[attributes.headers['myHeader'] == 'someValue']" >
              <http-policy:execute-next/>
           </when>
           <otherwise>
              <logger message="Avoid Flow execution" />
           </otherwise>
        </choice>
      </http-policy:source>
  </http-policy:proxy>

Using extensions

Policies, just like Mule applications, can make use of Mule extensions or plugins to extend the Mule Core capabilities.

For example, a policy is required to add additional headers to the HTTP Response from a flow’s HTTP Listener.
The first step is to add a Maven dependency that can modify an HTTP Request object.

The mule-http-policy-transform-extension Mule plugin can modify HTTP Requests.

   <dependencies>
       <dependency>
           <groupId>com.mulesoft.anypoint</groupId>
           <artifactId>mule-http-policy-transform-extension</artifactId>
           <version>1.0.0</version>
           <classifier>mule-plugin</classifier>
       </dependency>
   </dependencies>

Next, the XML http-transform namespace must be added to expose the operations in the above dependency.

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesoft.org/schema/mule/core"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:http-policy="http://www.mulesoft.org/schema/mule/http-policy"
     xmlns:http-transform="http://www.mulesoft.org/schema/mule/http-policy-transform"
     xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
              http://www.mulesoft.org/schema/mule/http-policy http://www.mulesoft.org/schema/mule/http-policy/current/mule-http-policy.xsd
              http://www.mulesoft.org/schema/mule/http-policy-transform http://www.mulesoft.org/schema/mule/http-policy-transform/current/mule-http-policy-transform.xsd">

   <http-policy:proxy name="policy">
       <http-policy:source>
           <http-policy:execute-next/>

           <http-transform:add-headers outputType="response">
               <http-transform:headers>#[{'policyHeader': 'policyHeaderValue'}]</http-transform:headers>
           </http-transform:add-headers>
       </http-policy:source>
   </http-policy:proxy>
</mule>

If a policy needs to use custom code, the policy can either:

  1. Import a custom Mule plugin programmed with the Java or XML SDK Extension

  2. Use the <scripting:execute> element to add in custom scripts

The recommended method is to use the SDK Extensions.

It is not possible for a policy to use the Java Module because the Java Module requires exported Java classes. Policies are not allowed to export resources nor packages such as Java classes.

Outbound policies

Policies can be applied to outbound HTTP Requests within a flow as well. This capability enables policies to inject additional headers and other information into outbound HTTP traffic through an HTTP Requester defined in a flow.

Below is an example of a policy that contains source and operation blocks:

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:http-policy="http://www.mulesoft.org/schema/mule/http-policy">

  <http-policy:proxy name="policy-template">  (1)
      <http-policy:source>
     …
      <http-policy:execute-next/>
     …
      </http-policy:operation> (2)
  </http-policy:proxy>
</mule>
1 One http-policy:proxy element is used for both types of policy blocks. Both source and operation blocks may be present. When both blocks are present, each block can share variables to keep state throughout the policy execution.
2 This policy block contains code to be executed after the flow’s HTTP Requester returns an HTTP response. If the flow does not contain an HTTP Requester element, then this block is never executed.

In general, the http-policy:operation block allows a policy to inject code before Mule execution reaches an HTTP Requester and after an HTTP Requester returns an HTTP response. The operation block can contain an http-policy:execute-next element to control operations before and after an HTTP Request in a flow.

Execution order example

There are two policies, A and B.

Policy A has order 1 and Policy B has order 2.

Policy A is defined by the following configuration:

  <http-policy:proxy name="policy-A">
     <http-policy:source>
        <A1 />
        <http-policy:execute-next/>
        <A2 />
     </http-policy:source>

     <http-policy:operation>
        <A3 />
        <http-policy:execute-next/>
        <A4 />
     </http-policy:operation>
  </http-policy:proxy>

And policy B config is:

  <http-policy:proxy name="policy-B">
     <http-policy:source>
        <B1 />
        <http-policy:execute-next/>
        <B2 />
     </http-policy:source>

     <http-policy:operation>
        <B3 />
        <http-policy:execute-next/>
        <B4 />
     </http-policy:operation>
  </http-policy:proxy>

A flow is defined as:

  <flow name="flow">
      <http:listener />
      <F1/>
      <http:requester />
      <F2/>
  </flow>

When an HTTP Request arrives to the Mule runtime, the execution order follows the diagram below:

<A1> → <B1> → <F1> → <A3> → <B3> → <http:requester> → <B4> → <A4> → <F2> → <B2> → <A2>

Operation policies are only injected around the http:requester operation.

Error Handling

Mule 4 policies can handle errors thrown by

  1. The policy

  2. A flow within the Mule application

  3. Other policies

Error handling can be accomplished using Mule 4’s try and error-handler elements.

Once an error is caught by an error-handler, the error is either, propagated up the Mule Event processing chain, or handled, where normal Mule event process execution continues.

For example, consider the following policy and flow:

  <http-policy:proxy name="policy">
     <http-policy:source>
        <try>
           <P1 />
           <http-policy:execute-next/>
           <P2 />
           <error-handler>
              <on-error-continue>
                 <PEH />
              </on-error-continue>
           </error-handler>
        </try>
      </http-policy:source>
  </http-policy:proxy>
  <flow name="flow">
     <http:listener />
     <F1 />
     <F2 />
     <error-handler>
        <on-error-continue>
           <FEH />
        </on-error-continue>
     </error-handler>
  </flow>

Scenario 1

Assume <F1> raises an error. The execution order follows the diagram below:

<P1> → <F1> → <FEH> → <P2>

<F2> is not executed, and processing continues into the flow’s error-handler.
Since the flow’s error-handler is configured not to propagate errors, <FEH> will return to the policy and <P2> executes instead of the policy’s error-handler.

Scenario 2

Assume <P1> raises an error. The execution order follows the diagram below:

<P1> → <PEH>

From the example above, the flow never executes.

Scenario 3

Assume now that the flow’s error handler propagates errors.

  <error-handler>
     <on-error-propagate>
        <FEH />
     </on-error-propagate>
  </error-handler>

Assume <F1> raises an error. The execution order follows the diagram below:

<P1> → <F1> → <FEH> → <PEH>

The error gets propagated back to the policy, and the policy’s error handler continues handling the error.

In summary, error handlers provide an alternative method to conditionally execute a flow within a policy.

Classloading isolation

Between policies

Policies contain the same classloading isolation architecture seen in Mule 4 applications: any resource or library that a policy defines is not visible to other policies.

Between a Policy and an Application

Classloading between policies and Mule 4 applications is not completely isolated. This scenario is similar to classloading isolation between applications and domains:

Any plugin, library, or resource visible to the application is also visible to any policy applied to that application.

However, any plugin, library, or resource visible to a policy is not visible to the application applied.

Dependency resolution

If a policy and an application use different versions of the same dependency, the application’s dependency version will be used by the policy.

You can read more on classloading isolation in the Classloading Isolation topic.

Variables and Event Scope

A policy can define any number of variables. Variables within a policy scope can be shared between policy blocks. For example, a variable maxCount defined in a http-policy:source block is available in a subsequent http-policy:operation block.

However, any variables defined in a policy are not available to other polices and to the application.
Furthermore, variables defined by the application are not available to any policy.

Mule message propagation in source policies

Policies can make changes to the Mule message, but the changes may not get propagated, depending on where the Mule message changes are made relative to the http-policy:execute-next element.

For source policies, any modification to a Mule Message made after the http-policy:execute-next element, will continue propagation throughout the rest of the Mule event processing chain.

The below policy and flow illustrates this concept:

<http-policy:proxy name="policy">
  <http-policy:source>
     <http-policy:execute-next/>
     <set-payload value="Policy Message" />
   </http-policy:source>
</http-policy:proxy>
<flow name="flow">
  <http:listener />
  <set-payload value="Flow Message" />
</flow>

The final response back to the client will be an HTTP Response that contains "Policy Message" as the body.

However, modifications made before the execute-next element, are not propagated to the next policy or application by default.

Consider the below policy and flow:

<http-policy:proxy name="policy">
  <http-policy:source>
     <set-payload value="Policy Message" />
     <http-policy:execute-next/>
  </http-policy:source>
</http-policy:proxy>
<flow name="flow">
  <http:listener />
  <logger message=#[payload] />
</flow>

The final response back to the client will be an HTTP Response that contains an empty body. Furthermore, the logger in the flow will log an empty payload.

Propagating the Mule message

Within the http-policy:source tag, set the attribute propagateMessageTransformations to true to enable propagation.

<http-policy:proxy name="policy">
  <http-policy:source propagateMessageTransformations="true">
     <set-payload value="Policy Message" />
     <http-policy:execute-next/>
  </http-policy:source>
</http-policy:proxy>
<flow name="flow">
  <http:listener />
  <logger message=#[payload] />
</flow>

The final response back to the client will be an HTTP Response that contains "Policy Message" as the body. The logger within the flow will log "Policy Message."

This design prevents unintentional modifications that can affect the application.

Mule message propagation in operation policies

Mule message propagation is similar to source policies but in the opposite direction. In operation policies, modifications made before the execute-next element are always propagated. Modifications made after the execute-next element, are not propagated by default.

Propagation can be enabled using the same attribute propagateMessageTransformations in the operation policy definition:

<http-policy:proxy name="scope-payload">
   <http-policy:operation propagateMessageTransformations="true">
       …
       <http-policy:execute-next/>
       …
   </http-policy:operation>
</http-policy:proxy>

In summary, variables cannot be used to share information from a policy to other policies or Mule applications.

However, Mule messages can be used to share information from a policy to other policies or Mule applications. Dependent on where the Mule message is set within a policy block, the attribute propagateMessageTransformations may need to be set to true to enable Mule message propagation.

Authentication (Security Context)

User authentication can be exposed through the Authentication object within the Security context object.

If a policy sets the Authentication object, it will be available to other policies and to the application.
The Authentication object can be accessed using DataWeave:

#[authentication.principal]
#[authentication.password]
#[authentication.properties.someProperty]

The only method to set the Authentication object is through a dependency using the SDK Mule extension.
Refer to the Authentication Handler article to learn how to set the authentication object.

Mule 4 Provided Policies use this exact method to propagate client information.

YAML Configuration File

Mule 4’s policies use YAML files to store metadata and user parameters. This flexible design allows a policy to work across multiple APIs that require different user parameters and configurations.

For example, the Rate Limit Policy allows for different configurations based on user parameters: a user may want to allow up to 100 requests per minute on one API, and allow 5000 per minute on a different API.

To allow user parameters, policy developers define user input in the YAML Configuration file. The file is then used by API Manager to render the UI for user input.

Example of a Client ID enforcement YAML file

id: openam-access-token-enforcement  (1)
name: OpenAM access token enforcement  (2)
supportedPoliciesVersions: '>=v4'  (3)
description: Enforces access tokens by OpenAM.  (4)
category: Security  (5)
violationCategory: authentication  (6)
type: system  (7)
resourceLevelSupported: true  (8)
standalone: true  (9)
identityManagement:  (10)
type: OpenAM
- OAuth 2.0 protected
configuration:  (11)
- propertyName: scopes
  name: Scopes
  description: A space-separated list of supported scopes
  type: string
  optional: true
  sensitive: false
  allowMultiple: false
- propertyName: exposeHeaders
  name: Expose Headers
  description: In a proxy scenario, defines if headers should be exposed in the request to the backend. The headers that may
      be sent are the user properties returned by the federation server when validating the access token with a 'X-AGW-' prefix.
  type: boolean
  optional: true
  defaultValue: true
  allowMultiple: false
1 Unique ID within your organization of the policy. Mandatory
2 User friendly name that is used for displaying the policy name in API Manager’s UI. Mandatory
3 Deprecated property. Value should be set to ‘>=v1’ for now. Mandatory
4 Description of what the policy does. Also used in API Manager’s UI. Mandatory
5 Category to which the policy belongs. Used to group and filter policies in API Manager’s UI, any String value is valid. Mandatory
6 Deprecated property. Value should be set to ‘system’. Mandatory
7 Value used by the Edge to show metrics about different types of policy violations. Mandatory
8 Whether resource level pointcuts should be enabled when applying the policy. Mandatory
9 Deprecated property. Value should be set to ‘true’. Mandatory
10 Whether policy requires information about an identity management that is configured to the API’s Organization. Optional
11 Where the policy parameters are defined. Every parameter listed here will be rendered as an expected user input in API Manager’s UI. It expects an array of values. Mandatory

Below is the syntax for defining the above policy’s parameters:

  propertyName: scopes (1)
  name: Scopes (2)
  description: A space-separated list of supported scopes (3)
  type: string (4)
  defaultValue: some String (5)
  optional: true (6)
  sensitive: false (7)
  allowMultiple: false (8)
1 Internal name of the parameter. Must be unique within the policy.
2 User friendly name of the parameter. Used for displaying in API Manager’s UI.
3 Description of the parameter. Also, used for displaying in API Manager’s UI.
4 Type of the parameter.
5 Default value for the parameter.
6 Whether is mandatory for the user to enter this value or not.
7 Whether this property should be masked when entering in API Manager’s UI.
8 Whether multiple values should be allowed for this parameter.

Parameter types

Depending of the type of the parameter, the UI will render a different type of input such as:

  • text boxes

  • radio buttons

  • checkboxes

Some rendered elements require additional configurations. The list of elements that require additional configurations are:

  • String: Any string expected.

  • Expression: A DataWeave expression starting with #[ and finished with ] is expected.

  • Boolean: true or false.

  • Int: A number is expected. This type requires additional properties.

  minimumValue: -1 (1)
  maximumValue: 2147483647 (2)
1 Minimum value allowed for the parameter.
2 Maximum value allowed for the parameter.
  • Radio: One value of a group of options. This type requires additional properties:

Options: (1)
- name: HTTP Basic Authentication Header
  value: httpBasicAuthenticationHeader
- name: Custom Expression
  value: customExpression
1 List of options for the user to choose. Each option has a name for displaying in the UI and an internal value used in the policy.
  • Keyvalues: Collection of Key-Value pairs.

HandleBars

Policies support Handlebars, a templating engine for resolving the configurable parameters of the policy and implementing semantic logic, such as conditionals. This is the preferred method of using user inputs in the policies.

Each policy parameter defined in a YAML Configuration file will be available as a HandleBars variable for resolving the final policy configuration.

Handlebars is an extension of Mustache, which was used in earlier versions of Mule policies.

Depending on the parameter type defined in the YAML, the variable will be of a different HandleBars type.

String, Expression, Radio, Int, and Boolean are primitive types in HandleBars.

The primitive types can be referenced from the policy template using curly brackets: {{{myproperty}}}

Keyvalues are complex types in HandleBars. Complex types have inner properties, and those can be referenced as follows:

{{{keyvalue.key}}}
{{{keyvalue.value}}}

There are some properties that are available to use in policies without being defined in the YAML Configuration file:

  • policyId id of the policy, useful for logging or naming a policy

  • isWsdlEndpoint indicates whether the API where the policy is being applied is a WSDL API.

When an Identity Management is defined for the organization where the API is being applied, then the following properties are also available:

identityManagementTokenUrl introspection endpoint of the identity management. identityManagementClientId client Id for authenticating to the introspection endpoint. identityManagementClientSecret client secret for authenticating to the introspection endpoint.

Pointcuts

In earlier versions, the pointcut element was required to configure a custom policy. Pointcuts specified the API that the policy operates.
In Mule 4, there is no need to configure the pointcut element. Information about the API on which the custom policy operates is provided by API Manager when a policy is applied.

See offline policies for configuration guidelines when a policy is not applied online.

We use cookies to make interactions with our websites and services easy and meaningful, to better understand how they are used and to tailor advertising. You can read more and make your cookie choices here. By continuing to use this site you are giving us your consent to do this.