Send Docs Feedback

Access Control policy

What

The Access Control policy lets you allow or deny access to your APIs by specific IP addresses.

Where

This policy can be attached in the following locations.

ProxyEndpoint TargetEndpoint
    PreFlow Flow PostFlow PreFlow Flow PostFlow    
Request    
    Response
    PostFlow Flow PreFlow PostFlow Flow PreFlow    

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 attribute in the Element reference for more information.

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

Deny all requests from client address: 10.10.10.10

Allow requests from any other client address.

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

Deny all requests from client address: 10.10.10.*

Allow requests from any other client address.

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

Deny all requests from client address: 10.10.*.*

Allow requests from any other client address.

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

Deny all requests from client address: 10.10.10.*, but allow 10.10.10.20.

Allow requests from any other client address.

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

Allow all requests from address: 10.10.*.*

Deny requests from any other client address.

<AccessControl name="ACL">
  <IPRules noRuleMatchAction="/DENY">
    <MatchRule action="/ALLOW">
      <SourceAddress mask="24">10.10.20.0</SourceAddress>
      <SourceAddress mask="24">10.10.30.0</SourceAddress>
      <SourceAddress mask="24">10.10.40.0</SourceAddress>
     </MatchRule>
  </IPRules>
</AccessControl>

Whitelist (allow requests from) client addresses: 10.10.20.* 10.10.30.* 10.10.40.*

Deny all other addresses.

<AccessControl name="ACL">
  <IPRules noRuleMatchAction="/ALLOW">
    <MatchRule action="/DENY">
      <SourceAddress mask="24">10.10.20.0</SourceAddress>
      <SourceAddress mask="24">10.10.30.0</SourceAddress>
      <SourceAddress mask="24">10.10.40.0</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>

Blacklist (deny requests from) client addresses: 10.10.20.* 10.10.30.* 10.10.40.*

Allow all other addresses.

<AccessControl name="ACL">
  <IPRules noRuleMatchAction="/DENY">
    <MatchRule action="/DENY">
      <SourceAddress mask="24">10.10.0.0</SourceAddress>
      <SourceAddress mask="24">10.20.0.0</SourceAddress>
      <SourceAddress mask="24">10.30.0.0</SourceAddress>
    </MatchRule>
    <MatchRule action="/ALLOW">
      <SourceAddress mask="16">10.10.0.0</SourceAddress>
      <SourceAddress mask="16">10.20.0.0</SourceAddress>
      <SourceAddress mask="16">10.30.0.0</SourceAddress>
    </MatchRule>
  </IPRules>
</AccessControl>

Whitelist: 10.10.*.* 10.20.*.* 10.30.*.*

Blacklist a subset of the whitelist: 10.10.0.* 10.20.0.* 10.30.0.*


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 (or whitelist) 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).
    • 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.
    • The X-FORWARDED-FOR header is considered the source address. If there are multiple addresses in the header, use the <ValidateBasedOn> element to control which are evaluated.
  • 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.

About the X-Forwarded-For HTTP header

The Access Control policy evaulates the IP addresses in the X-Forwarded-For HTTP header. Edge automatically populates that 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, the trusted, auto-populated IP is the last 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:

111.222.333.444,111.111.111.111,73.153.16.114

then the last value, 73.153.16.114, is the trusted IP that's auto-populated by Edge.

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 10.20.30.40 looks like this in binary:

00001010 . 00010100 . 00011110 . 00101000

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:

10.20.30.40/16

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

This notation means, "Keep the first 16 bits exactly as is, the remaining bits can be anything." For example:

Notice that the mask happens at the end of group two. This makes things nice and tidy, in essence creating a mask like this: 10.20.*.*. 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 22:

Here it gets a litle tricky: keep the first 22 bits and allow anything in the rest—per group. For example, as shown above, groups 1 and 2 can be any number 0-255. But because group 3 gets truncated by the CIDR notation, it means keep the first 6 bits, and the last two can vary. When you translate the binary, it means there are four possible combinations (00, 01, 10, 11) that can be added onto the leading 000111, which must stay as is. In other words, these binary combinations are possible:

  • 00011100 = 28
  • 00011101 = 29
  • 00011110 = 30
  • 00011111 = 31

Since none of group 4 is truncated by the mask, values can be anything from 0 to 255.

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

  • 10.20.28.*
  • 10.20.29.*
  • 10.20.30.*
  • 10.20.31.*

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">10.10.10.20</SourceAddress>
        </MatchRule>
        <MatchRule action="/DENY">
            <SourceAddress mask="24">10.10.10.20</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 attributes are common to all policy parent elements.

Attribute Description Default Presence
name

The internal name of the policy. Characters you can use in the name are restricted to: A-Z0-9._\-$ %. However, the Edge management UI enforces additional restrictions, such as automatically removing characters that are not alphanumeric.

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 the value of the policy's name attribute is used.

Presence: Optional
Type: String

 

<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">10.10.10.20</SourceAddress>
    </MatchRule>
    <MatchRule action="/DENY">
        <SourceAddress mask="24">10.10.10.20</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="32">10.10.10.20</SourceAddress>
    </MatchRule>
    <MatchRule action="/DENY">
        <SourceAddress mask="24">10.10.10.20</SourceAddress>
    </MatchRule>
</IPRules>
Default N/A
Presence Optional
Type String

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 (Classless Inter-Domain Routing). For example:

<SourceAddress mask="24">192.168.100.0</SourceAddress>

is equivalent to the following CIDR notation:

192.168.100.0/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.

For more guidance, see About IP masking with CIDR notation.

Integer N/A Required

<ValidateBasedOn> element

If the X-Forwarded-For HTTP header contains multiple IP addresses, use this ValidateBasedOn element to control which of the IP addresses is checked.

The last IP address listed in X-Forwarded-For is always the trusted, auto-populated IP address set by Edge. For more information, see About the X-Forwarded-For HTTP header.

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.

<ValidateBasedOn>X_FORWARDED_FOR_ALL_IP</ValidateBasedOn>
Default X_FORWARDED_FOR_ALL_IP
Presence Required
Type String
Valid values
  • X_FORWARDED_FOR_ALL_IP (default)
  • X_FORWARDED_FOR_FIRST_IP
  • X_FORWARDED_FOR_LAST_IP

See our GitHub repository samples for the most recent schemas.

Error codes

Errors returned from Edge policies follow a consistent format as described in the Error code reference.

The AccessControl Policy type returns the following error codes:

Error Code Message
accesscontrol.ClientIpExtractionFailed Client IP extraction failed
IPDeniedAccess Access Denied for client ip : {0}
InvalidIPAddress {0} is not a valid IP address
InvalidIPv4Address {0} is not a valid IPv4 address
InvalidIPv6Address {0} is not a valid IPv6 address
InvalidRulePattern Invalid rule pattern {0}

 

Help or comments?