You're viewing **Apigee Edge** documentation.  
[Go to the
**Apigee X** documentation](http://cloud.google.com/apigee/docs). info

![](https://docs.apigee.com/static/api-platform/images/icon_policy_security.jpg)

### What

The Access Control policy lets you allow or deny access to your APIs by specific IP
addresses.
**Video:** Watch a short video to learn more about how the to allow or deny
access to your APIs by specific IP addresses.
<iframe allowfullscreen frameborder="0" height="380" scrolling="no" src="https://www.youtube.com/embed/wlCFA8maquk" width="600"></iframe>

While you can attach this policy anywhere in the API proxy flow, you'll most likely want to
check IP addresses at the beginning of the flow ( Request / ProxyEndpoint / PreFlow), even before
authentication or quota checking.

### Samples

The mask values in the following IPv4 samples identify which of the four octets (8, 16, 24, 32
bits) the match rule considers when allowing or denying access. The default value is 32. See the
[`mask`](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#sourceaddress) attribute in the Element reference for more
information.

### Deny 198.51.100.1

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "DENY">
      <SourceAddress mask="32">198.51.100.1</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>
```

Deny all requests from client address: 198.51.100.1

Allow requests from any other client address.

### Deny using variables

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "DENY">
      <SourceAddress mask="{kvm.mask.value}">{kvm.ip.value}</SourceAddress>
    </MatchRule>
    </IPRules>
</AccessControl>
```

Suppose you're using a key value map (KVM) to store values for masking and IPs.
This is a handy approach to changing IPs and masking during runtime without having to update
and redeploy your API proxy. You can use the [KeyValueMapOperations policy](https://docs.apigee.com/api-platform/reference/policies/key-value-map-operations-policy) to retrieve
the variables containing the values for `kvm.mask.value` and
`kvm.ip.value` (assuming that's what you named the variables in your KVM policy
that contain the values of the mask and IP values from your KVM).
If the values you retrieved were `24` for the mask and `198.51.100.1`
for the IP address, the AccessControl policy would deny all requests from: 198.51.100.\*

All other client addresses would be allowed.

### Deny 198.51.100.\*

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "DENY">
      <SourceAddress mask="24">198.51.100.1</SourceAddress>
    </MatchRule>
    </IPRules>
</AccessControl>
```

Deny all requests from client address: 198.51.100.\*

Allow requests from any other client address.

### 198.51.\*.\*

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "DENY">
       <SourceAddress mask="16">198.51.100.1</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>
```

Deny all requests from client address: 198.51.\*.\*

Allow requests from any other client address.

### Deny 198.51.100.\*, allow 192.0.2.1

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "ALLOW">
      <SourceAddress mask="32">192.0.2.1</SourceAddress>
    </MatchRule>
    <MatchRule action = "DENY">
      <SourceAddress mask="24">198.51.100.1</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>
```

Deny all requests from client address: 198.51.100.\*, but allow 192.0.2.1.

Allow requests from any other client address.

### Allow 198.51.\*.\*

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "DENY">
    <MatchRule action = "ALLOW">
      <SourceAddress mask="16">198.51.100.1</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>
```

Allow all requests from address: 198.51.\*.\*

Deny requests from any other client address.

### Allow multiple IPs

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "DENY">
    <MatchRule action = "ALLOW">
      <SourceAddress mask="24">198.51.100.1</SourceAddress>
      <SourceAddress mask="24">192.0.2.1</SourceAddress>
      <SourceAddress mask="24">203.0.113.1</SourceAddress>
     </MatchRule>
  </IPRules>
</AccessControl>
```

Allow requests from client addresses: 198.51.100.\* 192.0.2.\* 203.0.113.\*

Deny all other addresses.

### Deny multiple IPs

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "DENY">
      <SourceAddress mask="24">198.51.100.1</SourceAddress>
      <SourceAddress mask="24">192.0.2.1</SourceAddress>
      <SourceAddress mask="24">203.0.113.1</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>
```

Deny requests from client addresses: 198.51.100.\* 192.0.2.\* 203.0.113.\*

Allow all other addresses.

### Allow multiple IPs, deny multiple IPs

```
<AccessControl name="ACL">
  <IPRules noRuleMatchAction = "DENY">
    <MatchRule action = "DENY">
      <SourceAddress mask="24">198.51.100.1</SourceAddress>
      <SourceAddress mask="24">192.0.2.1</SourceAddress>
      <SourceAddress mask="24">203.0.113.1</SourceAddress>
    </MatchRule>
    <MatchRule action = "ALLOW">
      <SourceAddress mask="16">198.51.100.1</SourceAddress>
      <SourceAddress mask="16">192.0.2.1</SourceAddress>
      <SourceAddress mask="16">203.0.113.1</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>
```

Allow: 198.51.\*.\* 192.0.\*.\* 203.0.\*.\*

Deny a subset of the allow list: 198.51.100.\* 192.0.2.\* 203.0.113.\*

*** ** * ** ***

## Usage notes

In addition to protecting your APIs against malicious IPs, the Access Control policy also
gives you control over legitimate IP access. For example, if you only want computers under the
control of your enterprise to access the APIs exposed in your test environment, you can allow
the IP address range for your internal network. Developers working from home can
access these APIs using VPN.

The configuration and execution of an Access Control policy involves the following:

- Define a set of *match rules* with one of two actions (ALLOW or DENY) associated with each.
- For each match rule, specify the IP address (SourceAddress element).
  - See [How the policy chooses which IP address to evaluate](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#xforwardedfor) to determine which IP address(es) in the message you're configuring rules to handle.
  - Configure a mask for each IP address. You allow or deny access based on a mask value on the IP address. See [About IP masking with CIDR notation](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#cidr).
- Specify the order in which the rules are tested.
- All the match rules are executed in the given order. When a rules matches, the corresponding action is executed and following match rules are skipped.
  - If the same rule is configured with both ALLOW and DENY actions, the rule that is defined first in the order is triggered and the subsequent rule (with the other action) is skipped.

### How the policy chooses which IP address to evaluate

IP addresses can come from various sources in a request. For example, the
`True-Client-IP` message header might contain an IP address, and the
`X-Forwarded-For` header may contain one or more IP addresses. This section
describes how to configure the AccessControl policy to evaluate the exact IP address(es) you
want it to evaluate.

Following is the logic the AccessControl policy uses to decide which IP address to
evaluate:

#### 1. True-Client-IP header

The policy first checks for an IP address in the `True-Client-IP` header. If
the header contains a valid IP address, the policy evaluates that address.

> [!WARNING]
> **Warning:** If you're going to use the `True-Client-IP` header, be sure you absolutely trust the source of that address. If you can't ensure that the header contains a trusted address, set [`<IgnoreTrueClientIPHeader>true</IgnoreTrueClientIPHeader>`](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#ignoretrueclientipheaderelement) so that the policy ignores the `True-Client-IP` and instead evaluates the IP address(es) in the `X-Forwarded-For` header.

#### 2. X-Forwarded-For header

If there's no `True-Client-IP` header, or if you've set the
[\<IgnoreTrueClientIPHeader\>](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#ignoretrueclientipheaderelement) element to
true, the policy evaluates the IP address(es) in the `X-Forwarded-For` header.

Edge automatically populates the `X-Forwarded-For` header
with the IP address it received from the last external TCP handshake (such as the client IP or
router). If there are multiple IP addresses in the header, those addresses
are likely the chain of servers that processed a request. However, the list of addresses
could also contain a spoofed IP address. So how does the policy know which addresses to
evaluate?

Your organization configuration and policy configuration determine which
`X-Forwarded-For` address(es) the policy evaluates.

First, check to see if the `feature.enableMultipleXForwardCheckForACL` property
is set on your organization. You can use the
[Get organization](https://apidocs.apigee.com/docs/organizations/1/routes/organizations/%7Borg_name%7D/get) API to check. Then:

- If you don't see the `feature.enableMultipleXForwardCheckForACL` in your organization's list of properties, it means that property is set to **false** (the default). With this property set to false, the policy evaluates the **last** address in the header (visible in the [Trace tool](https://docs.apigee.com/api-platform/debug/using-trace-tool-0)), which is the IP address Edge received from the last external TCP handshake.

  > [!WARNING]
  > **WARNING:** In Edge for Private Cloud, the behavior of the
  > `X-Forwarded-For` HTTP header depends on the version you are using:
  > - **Version 4.18.05 and later:** Edge automatically populates the `X-Forwarded-For` HTTP header with the single IP address it received from the *last* external TCP handshake (such as the client IP or router). That means `X-Forwarded-For` contains only a single IP address.
  > - **Version 4.18.01 and earlier:** Edge automatically populates the `X-Forwarded-For` HTTP header with the *first* IP address it received from the last external TCP handshake (such as the client IP or router).
  >
  >   If there are multiple IP addresses in the header, the trusted, auto-populated IP is the
  >   **first** one listed. For example, if the `X-Forwarded-For` header in the
  >   request to an API proxy (viewed in the Trace tool) contains the following:
  >
  >   ```
  >   198.51.100.1, 192.0.2.1, 203.0.113.1
  >   ```
  >
  >   then the first value, 198.51.100.1, is the trusted IP that's auto-populated by Edge.
  >
  >   By default, Edge ignores any `X-Forwarded-For` IPs in the header except the
  >   first address, which is the IP address Edge received from the first external TCP handshake.

- If the `feature.enableMultipleXForwardCheckForACL` on your organization is set to true, configure the [\<ValidateBasedOn\>](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#validatebasedon) element to determine which IP addresses the policy evaluates.

#### Changing the `feature.enableMultipleXForwardCheckForACL` property

Edge Organization Administrators can use the
[Update organization properties](https://apidocs.apigee.com/docs/organizations/1/routes/organizations/%7Borg_name%7D/post) API to set the
`feature.enableMultipleXForwardCheckForACL` property.

> [!NOTE]
> If you're an Edge for Public Cloud customer, contact [Apigee Edge Support](https://docs.apigee.com/api-platform/troubleshoot/support) to restart the message processors after setting the organization property.

The following API example sets the property in Edge for Private Cloud.
**If there are other properties set on your organization, be sure to include those as well.
Otherwise, they'll be removed**.

```
curl -u email:password -X POST -H "Content-type:application/xml" http://host:8080/v1/o/myorg -d \
"<Organization type="trial" name="MyOrganization">
    <DisplayName>MyOrganization</DisplayName>
    <Properties>
        \<Property name="feature.enableMultipleXForwardCheckForACL">true</Property>
        \<!-- Include other existing properties as well. --\>
    </Properties>
</Organization>"
```

In Edge for Private Cloud, after changing the value of the
`feature.enableMultipleXForwardCheckForACL` property,
you must restart your message processors, as described in
[Start/stop/restart individual components](https://docs.apigee.com/private-cloud/latest/starting-stopping-and-restarting-apigee-edge#startstoprestart-individual-components).

#### X-Forwarded-For dimensions in Apigee analytics

Edge Analytics writes the value of the `X-Forwarded-For` header to the
`x_forwarded_for_ip` dimension. To determine the client IP that made
the request to Edge, use the values in the `ax_true_client_ip` or
`ax_resolved_client_ip` dimenstions. See
[Analytics metrics, dimensions,
and filters reference](https://docs.apigee.com/api-platform/analytics/analytics-reference) for more.

### About IP masking with CIDR notation

CIDR notation (Classless Inter-Domain Routing) is a way of indicating a range of IP addresses
through masking. It applies to both IPv4 and IPv6. Here's how it works. We'll use IPv4 in our
examples for simplicity.

IP addresses are groups of numbers separated by periods. In binary terms, each group is a
specific number of bits (8 for IPv4 and 16 for IPv6). The IPv4 address 198.51.100.1 looks like
this in binary:

`11000110.00110011.01100100.00000001`

That's 4 groups of 8 bits, or 32 total bits. With CIDR, you can indicate a range by adding a
/number (1-32) to the IP address, like this:

`198.51.100.1/24`

In this case, the 24 is the number you would use for the `mask` attribute
value in this policy.

This notation means, "Keep the first 24 bits exactly as is, the remaining bits can be
any value 0 through 255." For example:

| Keep these exactly as is | Possible values for the last group |
|---|---|
| 198.51.100. | 0 - 255 |

Notice that the mask happens at the end of group three. This makes things nice and tidy, in
essence creating a mask like this: 198.51.100.\*. In most cases, using multiples of 8 (IPv4) and 16
(IPv6) will give you the masking level you want:

IPv4: 8, 16, 24, 32

IPv6: 16, 32, 48, 64, 80, 96, 112, 128

However, you can user other numbers for finer-grained control, which involves a little binary
calculation. Here's an example using a mask of 30, as in **198.51.100.1/30**, where the last
1 is 00000001 in binary:

| Keep these exactly as is | Possible values |
|---|---|
| **11000110.00110011.01100100.000000** (first 30 bits) | 000000**00** , 000000**01** , 000000**10** , or 000000**11** |
| **198.51.100.** | 0, 1, 2, or 3 |

In this example, with the configuration set to `<SourceAddress
mask="30">198.51.100.1</SourceAddress>`, the following IPs would be allowed (or
denied, depending on your rules):

- 198.51.100.0
- 198.51.100.1
- 198.51.100.2
- 198.51.100.3

## Element reference

The element reference describes the elements and attributes of the Access Control policy.

```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AccessControl async="false" continueOnError="false" enabled="true" name="Access-Control-1">
    <DisplayName>Access Control 1</DisplayName>
    <IPRules noRuleMatchAction = "ALLOW">
        <MatchRule action = "ALLOW">
            <SourceAddress mask="32">198.51.100.1</SourceAddress>
        </MatchRule>
        <MatchRule action = "DENY">
            <SourceAddress mask="24">198.51.100.1</SourceAddress>
        </MatchRule>
    </IPRules>
    <ValidateBasedOn>X_FORWARDED_FOR_ALL_IP</ValidateBasedOn>
</AccessControl>
```

## \<AccessControl\> attributes

```
<AccessControl async="false" continueOnError="false" enabled="true" name="Access-Control-1"> 
```

The following table describes attributes that are common to all policy parent elements:

| Attribute | Description | Default | Presence |
|---|---|---|---|
| `name` | The internal name of the policy. The value of the `name` attribute can contain letters, numbers, spaces, hyphens, underscores, and periods. This value cannot exceed 255 characters. Optionally, use the `<DisplayName>` element to label the policy in the management UI proxy editor with a different, natural-language name. | N/A | Required |
| `continueOnError` | Set to `false` to return an error when a policy fails. This is expected behavior for most policies. Set to `true` to have flow execution continue even after a policy fails. | false | Optional |
| `enabled` | Set to `true` to enforce the policy. Set to `false` to *turn off* the policy. The policy will not be enforced even if it remains attached to a flow. | true | Optional |
| `async` | This attribute is deprecated. | false | Deprecated |

## \<DisplayName\> element

Use in addition to the `name` attribute to label the policy in the
management UI proxy editor with a different, natural-language name.

```
<DisplayName>Policy Display Name</DisplayName>
```

| Default | N/A If you omit this element, the value of the policy's `name` attribute is used. |
| Presence | Optional |
| Type | String |
|---|---|

## \<IgnoreTrueClientIPHeader\> element

When you set this to true, the policy ignores the `True-Client-IP` header
and evaluates IP addresses in the `X-Forwarded-For` header, following the
[X-Forwarded-For evaluation behavior](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#xforwardedfor) you've configured.

> [!NOTE]
> **Note:** `<IgnoreTrueClientIPHeader>` is available in Apigee Edge versions 4.19.06.10 and later.

```
<AccessControl async="false" continueOnError="false" enabled="true" name="Access-Control-1">
    <DisplayName>Access Control-1</DisplayName>
    <IgnoreTrueClientIPHeader>true</IgnoreTrueClientIPHeader>
    ...
</AccessControl>
```

| Default | false |
| Presence | Optional |
| Type | Boolean |
|---|---|

## \<IPRules\> element

The parent element containing the rules that allow or deny IP addresses. The
`noRuleMatchAction` attribute lets you define how to handle any IP addresses that
aren't covered by your matching rules.

```
<IPRules noRuleMatchAction = "ALLOW">
```

| Default | N/A |
| Presence | Optional |
| Type | N/A |
|---|---|

### Attributes

| Attribute | Description | Type | Default | Presence |
|---|---|---|---|---|
| noRuleMatchAction | The action to take (allow or deny access) if the match rule specified is not resolved (unmatched). Valid value: ALLOW or DENY | String | ALLOW | Required |

## \<IPRules\>/\<MatchRule\> element

The action to take (allow or deny access) if the IP address matches the SourceAddress(es) you
define.

```
<IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "ALLOW">
        <SourceAddress mask="32">198.51.100.1</SourceAddress>
    </MatchRule>
    <MatchRule action = "DENY">
        <SourceAddress mask="24">198.51.100.1</SourceAddress>
    </MatchRule>
</IPRules>
```

| Default | N/A |
| Presence | Optional |
| Type | N/A |
|---|---|

### Attributes

| Attribute | Description | Type | Default | Presence |
|---|---|---|---|---|
| action | The action to take (allow or deny access) if the match rule specified is not resolved (unmatched). Valid value: ALLOW or DENY | String | ALLOW | Required |

## \<IPRules\>/\<MatchRule\>/\<SourceAddress\> element

The IP address range of a client.

Valid value: Valid IP address (dotted decimal notation). For wildcard behavior, use the
`mask` attribute.

```
<IPRules noRuleMatchAction = "ALLOW">
    <MatchRule action = "ALLOW">
        <SourceAddress mask="{variable}">198.51.100.1</SourceAddress>
    </MatchRule>
    <MatchRule action = "DENY">
        <SourceAddress mask="24">{variable}</SourceAddress>
    </MatchRule>
</IPRules>
```

As shown in the previous example, the `SourceAddress` element also supports
[Message templates](https://docs.apigee.com/api-platform/reference/message-template-intro) for the
`mask` attribute or IP address, which
means you can set the values using variables that are currently available in the
API proxy flow.

> [!NOTE]
> **Note:**For Edge for Private Cloud users, you must be on version 4.19.06 or later to use a variable.

For example, you can store an IP address in a key value map (KVM) and use the
[KeyValueMapOperations policy](https://docs.apigee.com/api-platform/reference/policies/key-value-map-operations-policy) to retrieve the IP address and assign it to a variable (such as
`kvm.ip.value`). You can then use that variable for the IP address:

`<SourceAddress mask="24">{kvm.ip.value}</SourceAddress>`

Setting mask and/or IP address with a variable gives you the flexibility to change values at
runtime without having to modify and re-deploy your API proxy.

| Default | N/A |
| Presence | Optional |
| Type | String (single IP address only) |
|---|---|

### Attributes

| Attribute | Description | Type | Default | Presence |
|---|---|---|---|---|
| mask | The `mask` attribute is a way to indicate the range of IP addresses to allow or deny. Mask is the equivalent of using [CIDR notation](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#cidr) (Classless Inter-Domain Routing). For example: `<SourceAddress mask="24">198.51.100.1</SourceAddress>` is equivalent to the following CIDR notation: 198.51.100.1/24 Valid values: IPv4: 1-32 IPv6: 1-128 A value of zero (0) is valid only for IP 0.0.0.0, hence impractical. **Set the mask with a variable** The `mask` attribute also supports [Message templates](https://docs.apigee.com/api-platform/reference/message-template-intro), which means you can set the value with a variable that's currently available in the API proxy flow. For example, you can store a mask value in a KVM and use the [KeyValueMapOperations policy](https://docs.apigee.com/api-platform/reference/policies/key-value-map-operations-policy) to retrieve the mask and assign it to a variable. To set the IP mask with the variable, use the following format, assuming the variable is named `kvm.mask.value`: `mask="{kvm.mask.value}"` | Integer | N/A | Required |

## \<ValidateBasedOn\> element

> [!NOTE]
> **Note:** To use this element, you need to change Edge's default behavior by setting the organization property `feature.enableMultipleXForwardCheckForACL`. The default behavior and how to change it are described in [How the
> policy chooses which IP address to evaluate](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#xforwardedfor).

When the `X-Forwarded-For` HTTP header contains multiple IP
addresses, use this `ValidateBasedOn` element to control which IP addresses are
evaluated.

Use this approach to evaluating a IP addresses only if you're certain about the validity
of the IP addresses you want to evaluate. For example, if you choose to evaluate all
IP addresses in the `X-Forwarded-For` header, you have to be able to trust the
validity of those addresses, and/or set up comprehensive DENY or ALLOW rules to let only trusted
IPs call your API proxy.

The leftmost IP address in the header belongs to the client, and the rightmost is the server
which forwarded the request to the current service. The rightmost, or last IP address,
is the address Edge received from the last external TCP handshake.

The value you enter in this element lets you determine whether to check all IP addresses in
the header (default), only the first IP address, or only the last IP address.

```
<AccessControl async="false" continueOnError="false" enabled="true" name="Access-Control-1">
    <DisplayName>Access Control 1</DisplayName>
    <IPRules noRuleMatchAction = "ALLOW">
        <MatchRule action = "DENY">
            <SourceAddress mask="32">198.51.100.1</SourceAddress>
        </MatchRule>
    </IPRules>
    <ValidateBasedOn>X_FORWARDED_FOR_ALL_IP</ValidateBasedOn>
</AccessControl>
```

| Default | `X_FORWARDED_FOR_ALL_IP` |
| Presence | Optional |
| Valid values | `X_FORWARDED_FOR_ALL_IP` (default) `X_FORWARDED_FOR_FIRST_IP` `X_FORWARDED_FOR_LAST_IP` |
|---|---|

## Schemas

Each policy type is defined by an XML schema (.xsd). For reference,
[policy schemas](https://github.com/apigee/api-platform-samples/tree/master/schemas/policy) are available on GitHub.

## Error reference

This section describes the fault codes and error messages that are returned and fault variables that are set by Edge when this policy triggers an error.
This information is important to know if you are developing fault rules to
handle faults. To learn more, see [What you need to know
about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors) and [Handling
faults](https://docs.apigee.com/api-platform/fundamentals/fault-handling).

### Runtime errors

These errors can occur when the policy executes.

> [!IMPORTANT]
> **Tip:** Use [API Monitoring](https://docs.apigee.com/api-monitoring) to investigate fault codes and diagnose issues faster. See [Set up a policy fault code alert](https://docs.apigee.com/api-monitoring/alerts-notifications#fault-code-alert) for an example. See [Fault code reference](https://docs.apigee.com/api-monitoring/fault-codes) for a complete list of all fault codes that you can handle with API Monitoring.

| Fault code | HTTP status | Cause | Fix |
|---|---|---|---|
| `accesscontrol.IPDeniedAccess` | 403 | The client IP address, or an IP address passed in the API request, matches an IP address specified in the `<SourceAddress>` element within the `<MatchRule>` element of the Access Control Policy, and the `action` attribute of the `<MatchRule>` element is set to `DENY`. | [](https://docs.apigee.com/api-platform/troubleshoot/policies/runtime/access-control-runtime-errors#ipdeniedaccess) |

### Fault variables

These variables are set when a runtime error occurs. For more information, see [Variables specific to policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors#variablesspecifictopolicyerrors).

| Variables | Where | Example |
|---|---|---|
| `fault.name="fault_name"` | <var translate="no">fault_name</var> is the name of the fault, as listed in the [Runtime errors](https://docs.apigee.com/api-platform/reference/policies/access-control-policy#runtime-errors) table above. The fault name is the last part of the fault code. | `fault.name Matches "IPDeniedAccess"` |
| `acl.policy_name.failed` | <var translate="no">policy_name</var> is the user-specified name of the policy that threw the fault. | `acl.AC-AllowAccess.failed = true` |

### Example fault response

> [!NOTE]
> **Note:** For fault handling, the best practice is to trap the `errorcode` part of the fault response. Do not rely on the text in the `faultstring` because it could change.

```
{
   "fault":{
     "faultstring":"Access Denied for client ip : 52.211.243.3"
      "detail":{
         "errorcode":"accesscontrol.IPDeniedAccess"
      }
   }
}
```

### Example fault rule

```
<FaultRule name="IPDeniedAccess">
    <Step>
        <Name>AM-IPDeniedAccess</Name>
        <Condition>(fault.name Matches "IPDeniedAccess") </Condition>
    </Step>
    <Condition>(acl.failed = true) </Condition>
</FaultRule>
```