Rules Files

Invariant will load and evaluate rules from YAML rules files found in your project directory. Rules can define traffic that should always be deliverable (critical flow rules) or never be deliverable (access policy rules) in your network.

Invariant rules files are YAML documents that conform to the specification on this page.

Overview

Invariant supports the following types of rules.

Rule type Direction Description
ingress-critical-flow ingress This traffic should always be successfully delivered.
egress-critical-flow egress
ingress-deny ingress This traffic should never be successfully delivered.
egress-deny egress
ingress-deny-others ingress Within a scope (e.g. TCP traffic), traffic should never be successfully delivered except where permitted.
egress-deny-others egress

Invariant rules are organized into policies which target the same ‘ingress’ or ‘egress’ network.

Directory

Invariant expects rules files to be placed in the directory invariant/policies/ relative to your project directory.

Structure

File structure

Invariant rules files must contain a list of policy objects under the top-level key access-policy.

Policy structure

A policy is a named group of related rules which target the same ‘ingress’ or ‘egress’ network. Invariant rules must be placed inside a policy.

The following fields can appear in a policy.

Field Required? Description
name Yes An identifier for this policy. Only characters -, _, A-Z, a-z, 0-9 are allowed.
comment No A long description for this policy.
owner No An email address or other identifier for the functional owner of this policy.
enforce No A boolean which can mark the policy unenforced if set to false. Defaults to true. Rules in unenforced policies are still tested but any violations are reported in a separate list.
ingress-network Yes (exactly one) The target network for the rules in this policy. A policy must define ‘ingress-network’ or ‘egress-network’, never both.
egress-network
rules Yes The list of rules in this policy.

Each policy has an inherent direction - ingress or egress - based on whether ingress-network or egress-network is specified. The rules in the policy must match it. So if the policy has ingress-network specified, only rules of type ‘ingress-critical-flow’, ‘ingress-deny’, and ‘ingress-deny-others’ should appear.

Network structure

A policy must have an ‘ingress-network’ or ‘egress-network’ and never both.

All rules in this policy must match the direction of the policy. A policy with ‘ingress-network’ defined may only contain ‘ingress’ rules. A policy with ‘egress-network’ defined may only contain ‘egress’ rules.

Both ‘ingress-network’ and ‘egress-network’ are typically specified as objects, but a shorthand version is available for both.

The following fields can appear in ‘ingress-network’.

Field Required? Description
destination-address Yes (at least one) Defines the ingress network IP space.
destination-exclude Subtracts from the ingress network IP space.

In shorthand mode, ‘ingress-network’ is specified as a CIDR, network name, or list of CIDRs and network names. This is exactly the same as providing destination-address. For example, the following policies are all identical.

access-policy:
  - name: dmz-ingress
    comment: example
    owner: example@example.com
    ingress-network:
        destination-address: 195.1.1.160/27 195.1.1.192/26


access-policy:
  - name: dmz-ingress
    comment: example
    owner: example@example.com
    ingress-network: 195.1.1.160/27 195.1.1.192/26


access-policy:
  - name: dmz-ingress
    comment: example
    owner: example@example.com
    ingress-network:
      - 195.1.1.160/27
      - 195.1.1.192/26


### invariant/policies/dmz.yaml
access-policy:
  - name: dmz-ingress
    comment: example
    owner: example@example.com
    ingress-network: DMZ

### def/networks.yaml
networks:
    DMZ:
        values:
          - address: 195.1.1.160/27
          - address: 195.1.1.192/26

The following fields can appear in ‘egress-network’.

Field Required? Description
source-address Yes (at least one) Defines the network IP space.
source-exclude Subtracts from the network IP space.
enter-interface No Consider traffic entering on these interfaces. Disables automatic interface selection.
source-interface No Consider traffic originating from these interfaces. Disables automatic interface selection.

Similar to ‘ingress-network’, an ‘egress-network’ with only ‘source-address’ can be specified in shorthand mode.

access-policy:
  - name: dmz-egress
    comment: example
    owner: example@example.com
    egress-network:
        source-address: DMZ


# Shorthand
access-policy:
  - name: dmz-egress
    comment: example
    owner: example@example.com
    egress-network: DMZ

Rule structure

Rules define testable statements about traffic that should always be deliverable (critical flow rules) or never be deliverable (access policy rules) in your network.

The permitted fields vary by the type of rule.

The following fields can appear in any rule.

Field Required? Description
type Yes The type of this rule. Must be a valid Invariant rule type.
comment No A long description for this rule.

The following fields can appear in rules with type ingress-critical-flow, egress-critical-flow, ingress-deny, egress-deny.

Field Required? Description
protocol No The space of possible protocol values for this traffic.
destination-address No The space of possible IP address values for the destination-address field of this traffic.
destination-exclude No Excludes IPs from the space of possible IP address values for the destination-address field of this traffic.
destination-port No The space of possible destination-port values for this traffic.
source-address No The space of possible IP address values for the source-address field of this traffic.
source-exclude No Excludes IPs from the space of possible IP address values for the source-address field of this traffic.
source-port No The space of possible source-port values for this traffic.
enter-interface No Consider traffic entering on these interfaces. Disables automatic interface selection.
source-interface No Consider traffic originating from these interfaces. Disables automatic interface selection.

Deny-others rules assert that no traffic should be deliverable to the target network except as permitted in the rule. These rules can be narrowed down using the ‘within’ section (typically these rules are narrowed by protocol at least).

The following fields can appear in rules with type ingress-deny-others, egress-deny-others.

Field Required? Description
within No Narrow the scope of this rule to within this traffic.
deny-all-except Yes Traffic to or from the network should never be deliverable except as permitted in this section.

Inside of a deny-others rule the ‘deny-all-except’ section can contain exactly one field:

Field Required? Description
flows Yes Traffic that is permitted for this rule.

The ‘within’ field and ‘flows’ field both contain a list of traffic flows. Those flows are defined using the same fields as critical-flow and deny rules above. This includes fields like ‘destination-address’, ‘destination-exclude’, ‘source-address’, and so on.

access-policy:
  - name: dmz-ingress
    comment: example
    owner: example@example.com
    ingress-network: DMZ
    rules:
      - type: ingress-deny-others
        comment: Limit SSH access to only from bastion network
        within:
          - protocol: TCP
            destination-port: SSH
        deny-all-except:
            flows:
                - comment: Internal SSH access
                  source-address: BASTION
                  destination-port: SSH
                  protocol: TCP

Field reference

Policy fields

The following fields can appear in a policy object.

name

Names the current policy. Only characters  -, _, A-Z, a-z, 0-9 are allowed.

comment

Describes the current policy.

Some best practices for the comment field:

  • All policies should use the comment field.
  • Include ticket references in the comment field if this policy was created or modified in response to a tracking ticket. This allows future users to understand the justification for the policy and confidently make changes to the network.

owner

Identifies the current owner of this policy.

Some best practices for the owner field:

  • The owner should be a primary contact who can comment on proposed changes to this policy.
  • Value should be an email address or other kind of identifier.

enforce

Mark the policy unenforced if set to false. Defaults to true.

Rules in unenforced policies are still tested but any violations are reported in a separate list.

ingress-network

Constrains the destination IP space the rules in this policy will apply to.

egress-network

Defines the source interfaces and source IP space the rules in this policy will apply to.

rules

The list of rules in this policy.

Rule fields

These fields can appear inside rules objects.

type

The type of this rule. Can be one of the following values.

  • ingress-critical-flow
  • egress-critical-flow
  • ingress-deny
  • egress-deny
  • ingress-deny-others
  • egress-deny-others

See Rule type reference for more information about each rule type.

within

Allowed only in deny-other rules. This constrains the scope of a deny-other rule using a list of traffic flows.

A simple way to think about ‘within’ is to look at a deny-other rule as a boolean expression.

IF traffic matches the network section

AND traffic matches the ‘within’ section

AND traffic is NOT in the ‘deny-all-except’ list

THEN the traffic is in violation of the rule.

Entries listed in the ‘within’ block are ‘OR’-ed together during rule evaluation.

deny-all-except

Allowed only in deny-other rules. This will define the only traffic that should be permitted for the target network (and within the scope of the ‘within’ section if provided).

It must contain an object with a single key, ‘flows’, which must contain a list of permitted traffic flows.

A simple way to think about deny-other rules is as a boolean expression.

IF traffic matches the network section

AND traffic matches the ‘within’ section

AND traffic is NOT in the ‘deny-all-except’ list

THEN the traffic is in violation of the rule.

Traffic flow fields

These fields can appear in several places:

  • Inside a critical-flow or deny rule.
  • Inside the ‘within’ section of a deny-other rule.
  • Inside the ‘deny-all-except’ section of a deny-other rule.
  • Inside the ‘ingress-network’ or ‘egress-network’ section of a policy (only certain fields are permitted in this case - see Network structure above).

Taken together these fields define traffic flows or classes of traffic.

Invariant thinks about traffic flows as a combination of the following:

  • Constraints on which interfaces to consider as points of ingress for the traffic.
  • Constraints on the packet field values.

We can categorize all of the fields in this section by whether they represent a constraint on packet field values (e.g. protocol) or a constraint on which interfaces to consider as points of ingress (enter-interface). Source-address / source-exclude and source-interface have the special property that they can create constraints on both.

These fields constrain packet field values only:

  • destination-address
  • destination-exclude
  • destination-port
  • source-port
  • protocol

These fields constrain which interfaces to consider as points of ingress only:

  • enter-interface

These fields can constrain both, depending on the situation:

  • source-address
  • source-exclude
  • source-interface

destination-address

Defines the space of possible IP address values for the destination-address field of this traffic.

If destination-exclude is also specified it will be subtracted from this IP space.

Acceptable values for destination-address are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

The following examples show different but equal ways to define destination-address as a list containing a /27 and a /26.

destination-address: 195.1.1.160/27 195.1.1.192/26


destination-address:
  - 195.1.1.160/27
  - 195.1.1.192/26


### invariant/policies/dmz.yaml
destination-address: DMZ

### def/networks.yaml
networks:
    DMZ:
        values:
          - address: 195.1.1.160/27
          - address: 195.1.1.192/26

destination-exclude

Excludes IPs from the space of possible IP address values for the destination-address field of this traffic.

If destination-address is not specified, destination-exclude is subtracted from the space of all IP addresses (0.0.0.0-255.255.255.255).

Acceptable values for destination-exclude are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

destination-port

Defines the space of possible values for the destination-port field of this traffic.

Acceptable values for destination-port are:

  • A string listing service names separated by a space (or a single service name).
  • A list of service names.

The destination-port field must agree with the protocol field. There are two agreement requirements:

  • All of the IP protocols specified must support the concept of a destination port if destination-port is specified.
  • All service names must be defined for all of the IP protocols specified.

To clarify this last point, it would be an error to create a rule that applies to MYSQL / UDP because the MYSQL service is defined only for TCP.

Invariant includes default definitions for many well-known ports. You can override these definitions or add your own custom service names. See well-known ports for a listing of default definitions and their values.

destination-port: HTTP HTTPS
protocol: tcp udp


destination-port:
  - HTTP
  - HTTPS
protocol: tcp udp


### invariant/policies/dmz.yaml
destination-port: HTTP
protocol: tcp udp

### def/services.yaml
services:
    HTTP:
      - port: 80
        protocol: tcp
      - port: 80
        protocol: udp

source-port

Defines the space of possible values for the source-port field of this traffic.

See destination-port above for details.

protocol

Defines the possible IP protocol values for this traffic.

The protocol field must agree with the destination-port and source-port fields. There are two agreement requirements:

  • All of the IP protocols specified must support the concept of a port if destination-port or source-port is specified.
  • All service names must be defined for all of the IP protocols specified.

A list of all acceptable IP protocol names is given on the Batfish documentation site here: https://batfish.readthedocs.io/en/latest/specifiers.html#ip-protocol-names.

source-address

Defines the space of possible source-address IP address values for this traffic. Also defines the interfaces to use as points of ingress for this traffic if source-interface and enter-interface are not specified.

This field follows the same conventions as the destination-address field described above.

If source-exclude is specified it will be subtracted from this IP space.

Acceptable values for source-address are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

Invariant must decide on interfaces to use as points of ingress for each rule. Source-address is used to identify good points of ingress when source-interface and enter-interface are not specified. The procedure for ingress interface selection is this:

  • First subtract source-exclude from source-address if specified.
  • Locate all network interfaces where the assigned IP address falls inside the source address space.
  • Locate all network interfaces where the primary IP network intersects the source address space.

The rule evaluation proceeds with an appropriate subset of the source address space considered for the matched interface.

  • For an interface where the assigned IP address falls inside the source address space, the question will be evaluated for traffic exiting this interface with source-address restricted to the assigned IP.
  • For an interface where the primary IP network intersects the source address space, the question will be evaluated for traffic entering this interface with source-address restricted to the intersection of the primary network and original source address space.
  • An interface can be evaluated twice if it matches both categories.

If enter-interface is specified for this traffic, Invariant will look at traffic entering those interfaces. The entire source address space will be considered as possible for all interfaces. No dynamic ingress selection will occur.

Source-address and source-exclude are not allowed if source-interface is specified.

source-exclude

Excludes IPs from the space of possible IP address values for the source-address field of this traffic.

If source-address is not specified, source-exclude is subtracted from the space of all IP addresses (0.0.0.0-255.255.255.255).

Acceptable values for source-exclude are:

  • A string listing CIDRs and/or network names separated by a space (or a single CIDR or network name).
  • A list of CIDRs and/or network names.

enter-interface

Consider traffic entering these interfaces.

All possible IP address values for source-address will be considered for each interface.

Enter-interface is useful for looking at spoofed, reflected, or one-way traffic. For example, if you have a part of your network that is especially untrusted (e.g. guest network, vendor network), you may want to write a rule that says traffic entering from certain interfaces should not be permitted to reach sensitive resources, even if the source of the traffic is a device generating malicious packets with spoofed source IP addresses.

Acceptable values are:

  • A string listing one or more location names separated by spaces.
  • A list of location names.

Location names are names that can resolve to specific interfaces. They are defined by placing a YAML file in the ‘invariant/locations/’ folder.

An example location which selects the GigabitEthernet0/1 interface on all edge routers might look like this. 

### In invariant/locations/edge.yaml
locations:
    EDGE_TO_INTERNET:
      - devices: border-.*
        interfaces: GigabitEthernet0/0

The following example shows two cases where enter-interface can be useful. Both cases use a scenario where we want our egress policy for the client VLANs to consider spoofed source addresses. The first policy approaches the problem by asserting that it applies to all traffic entering from the client network - regardless of source address. The second policy approaches the problem by creating a stand-alone policy which asserts that spoofed source IPs are always dropped, so that other policies do not need to worry about spoofed traffic.

access-policy:
  - name: client-egress
    comment: |
        This policy asserts that traffic entering the CLIENT_BORDER interfaces can reach
        only necessary resources on the network. It targets the CLIENT_BORDER interfaces
        directly to ensure the policy applies even to spoofed source addresses.
    owner: example@example.com
    egress-network:
        enter-interface: CLIENT_BORDER
    rules:
      - type: ingress-deny-others
        comment: Limit TCP/UDP access to DMZ network, external only
        within:
          - protocol: TCP UDP
        deny-all-except:
            flows:
                - comment: Client - DMZ
                  destination-address: DMZ
                  destination-port: HTTP HTTPS SSH
                - comment: Client - NTP
                  destination-address: NTP
                  destination-port: NTP
                - comment: Client - DNS
                  destination-address: DNS
                  destination-port: DNS
                - comment: Client - External
                  destination-exclude: RFC1918 DMZ

  - name: client-nospoof-egress
    comment: |
        This policy targets spoofed traffic entering the CLIENT_BORDER interfaces.
        It asserts that spoofed traffic is always dropped. With this policy in place
        we can safely create a normal egress policy that uses source-address: CLIENT_VLANS.
    owner: example@example.com
    egress-network:
      enter-interface: CLIENT_BORDER
      source-exclude: CLIENT_VLANS
    rules:
      - type: ingress-deny
        comment: Assert all spoofed traffic is dropped
        destination-address: ANY


### In invariant/locations/client.yaml
locations:
    CLIENT_BORDER:
      - devices: asa-1
        interfaces: GigabitEthernet0/1 GigabitEthernet0/3

### def/networks.yaml
networks:
    CLIENT_VLANS:
        values:
          - address: 192.172.0.0/14

source-interface

Consider traffic exiting these interfaces with source IP addresses matching each interface.

Source-interface cannot be used in combination with enter-interface or source-address (or source-exclude).

Acceptable values are:

  • A string listing one or more location names separated by spaces.
  • A list of location names.

Locations

The fields ‘enter-interface’ and ‘source-interface’ expect named locations. This section explains how named locations work and how to create them.

Overview

Named locations are essentially selectors for interfaces in your network.

Invariant will search for YAML files containing named location definitions in the ‘invariant/locations’ directory relative to the project root.

For example, CLIENT_BORDER here refers to two interfaces on device ‘asa-1’.

locations:
    CLIENT_BORDER:
      - devices: asa-1
        interfaces: GigabitEthernet0/1 GigabitEthernet0/3

Locations can use wildcards. In this example, EDGE_TO_INTERNET addresses interface GigabitEthernet0/0 on all devices with name matching “border-.*”.

locations:
    EDGE_TO_INTERNET:
      - devices: border-.*
        interfaces: GigabitEthernet0/0

Locations can be built up from other locations. We can define a new location, UNTRUSTED_INGRESS, to represent all boundary interfaces where high-risk traffic will enter the network. UNTRUSTED_INGRESS will use references to include all interfaces selected by CLIENT_BORDER or EDGE_TO_INTERNET.

locations:
    UNTRUSTED_INGRESS:
      - name: CLIENT_BORDER
      - name: EDGE_TO_INTERNET
    EDGE_TO_INTERNET:
      - devices: border-.*
        interfaces: GigabitEthernet0/0
    CLIENT_BORDER:
      - devices: asa-1
        interfaces: GigabitEthernet0/1 GigabitEthernet0/3

It can be helpful to think about these selectors as a boolean expression. For example, UNTRUSTED_INGRESS would be defined as:

All interfaces with:

  • Device name matching “border-.*”some text
    • AND interface name equal to GigabitEthernet0/0
  • OR
  • Device name equal to “asa-1”some text
    • AND interface name equal tosome text
      • GigabitEthernet0/1
      • OR
      • GigabitEthernet0/3

Location file directory

Invariant expects named locations to be defined in YAML files located in the directory invariant/locations/ relative to your project directory.

Location file structure

Location definition files must contain a mapping from location names to location definitions under the top-level key locations.

Location definition structure

A named location is defined using a list of selector objects. The location includes all interfaces matched by any of its selector objects.

The following fields can appear in a selector object.

Field Required? Description
devices No The device name must match. Can be an exact match or wildcard.
interfaces No The interface name must match. Can be an exact match or wildcard.
vrfs No The interface VRF name must match. Can be an exact match or wildcard. The default VRF is named “default”.
zones No The interface must belong to a matching zone (for devices with zones). Can be an exact match or wildcard.
ips No The interface primary assigned IP must fall inside this CIDR or named network.
name No Include all interfaces in another named location.

Location selector field reference

devices

Selects within devices (nodes) with matching names.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. .*, [a-z][a-z]* . 

interfaces

Selects within interfaces with matching names.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. .*, [a-z][a-z]* . 

vrfs

Selects within interfaces with matching VRF name.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. .*, [a-z][a-z]* . 

You may wish to examine the ‘interface_properties’ report in Invariant to get a sense of what VRF name is assigned to what interface. Interfaces are typically assigned to a VRF named ‘default’ when no VRF is explicitly associated.

zones

Selects within interfaces belonging to a zone with matching name.

This applies only to devices and nodes that support zones.

In the absence of special characters (asterisk, etc) this will look for exact matches. Wildcards and other regular expression syntax are permitted e.g. .*, [a-z][a-z]* . 

ips

Selects within interfaces where the primary assigned IP is inside this CIDR or named network.

For example, if we have the primary address of the interfaces pointed towards the internet on our edge routers tagged in our IPAM as “EDGE_TO_INTERNET” we can import that tag as a network name and use it here.

We might write a small python script to generate (or re-generate) network names from IPAM tags.

# In scripts/regenerate_ipam_networks.py
import sys
import yaml

def regenerate_networks_from_ipam_tags():
    ipam_tags = fetch_all_ipam_tags()
    # ipam_tags is like [{"name": "EDGE_TO_INTERNET", "ips": ["195.24.14.185", "195.24.14.187"]}]
    ipam_defs = {}
    for tag in ipam_tags:
        ipam_defs[tag.name] = {
            "values": [{"address": ip} for ip in tag.ips]
        }
    yaml.safe_dump(ipam_defs, sys.stdout)

if __name__ == "__main__":
    regenerate_networks_from_ipam_tags()

Then we can run the script periodically.

python scripts/regenerate_ipam_networks.py > def/generated_ipam_networks.yaml

Now we can create a policy which looks at traffic entering from the internet based on that IPAM label.

### In invariant/locations/edge.yaml
locations:
    EDGE_TO_INTERNET:
      - ips: EDGE_TO_INTERNET

### In invariant/policies/edge.yaml
access-policy:
  - name: internet-ingress
    comment: |
        This policy asserts that traffic entering the EDGE_TO_INTERNET interfaces can reach
        only necessary resources on the network. It targets the EDGE_TO_INTERNET interfaces
        directly to ensure the policy applies even to spoofed source addresses.
    owner: example@example.com
    ingress-network:
        enter-interface: EDGE_TO_INTERNET
    rules:
      - type: ingress-deny-others
        comment: Limit from-internet TCP/UDP access to specific DMZ services
        within:
          - protocol: TCP UDP
        deny-all-except:
            flows:
                - comment: Internet - DMZ web servers
                  destination-address: DMZ_WEB_SERVERS
                  destination-port: HTTP HTTPS

name

Include all interfaces that match another named location.

A selector containing the name field must be its own list item.

locations:
    UNTRUSTED_INGRESS:
      - name: CLIENT_BORDER
      - name: EDGE_TO_INTERNET

Rule type reference

ingress-critical-flow

Asserts that a traffic flow will always be delivered. Specifically this rule looks for any possible way a packet could be rejected, dropped, or fail to route within this class of traffic.

Example:

access-policy:
  - name: dmz-ingress
    comment: |
        This policy asserts that the DMZ network makes some services available to the internet.
    owner: example@example.com
    ingress-network: DMZ
    rules:
      - type: ingress-critical-flow
        comment: Ensure public HTTP/HTTPS access to DMZ resources
        protocol: TCP UDP
        destination-port: HTTP HTTPS

egress-critical-flow

Identical to ingress-critical-flow. Asserts that a traffic flow will always be delivered. Specifically this rule looks for any possible way a packet could be rejected, dropped, or fail to route within this class of traffic.

Examples:

access-policy:
  - name: basic-internet-access
    comment: |
        This policy asserts that some basic internet access (egress) is expected for the target networks.
    owner: example@example.com
    egress-network:
      - DMZ
      - VLAN30
      - CLIENT_VLANS
    rules:
      - type: egress-critical-flow
        comment: Ensure access to 1.1.1.1, 8.8.8.8 etc
        protocol: TCP UDP
        destination-address: GOOGLE_DNS CLOUDFLARE_DNS LEVEL3_DNS
        destination-port: DNS

  - name: dmz-access-needed
    comment: |
        This policy encodes critical dependencies for the DMZ network
    owner: example@example.com
    egress-network: DMZ
    rules:
      - type: egress-critical-flow
        comment: Ensure DMZ servers can send telemetry into the protected SEC_LOGS network 
        protocol: TCP UDP
        destination-address: SEC_LOGS
        destination-port: HTTPS

ingress-deny

Asserts that a traffic flow can never be successfully delivered. Specifically this rule looks for any possible way a packet could be successfully delivered within this class of traffic.

Example:

access-policy:
  - name: ingress-no-ssh
    comment: |
        This blanket policy asserts SSH access is denied for any traffic entering from the internet.
    owner: example@example.com
    ingress-network: RFC1918 DMZ
    rules:
      - type: ingress-deny
        comment: Ensure public SSH access is denied
        protocol: TCP UDP
        enter-interface: EDGE_FROM_INTERNET
        destination-port: SSH

egress-deny

Identical to ingress-deny. Asserts that a traffic flow can never be successfully delivered. Specifically this rule looks for any possible way a packet could be successfully delivered within this class of traffic.

Example:

access-policy:
  - name: egress-malicious-nets
    comment: |
        This blanket policy asserts outbound access is denied to certain malicious networks.
    owner: example@example.com
    egress-network: RFC1918
    rules:
      - type: egress-deny
        comment: Ensure outbound access to malicious networks is not allowed
        protocol: TCP UDP
        destination-address: MALICIOUS_PUBLIC_IPS

ingress-deny-others

Asserts that traffic can never be successfully delivered to the target network except for specific permitted flows. This rule looks for any possible way a forbidden packet could be successfully delivered.

The optional ‘within’ field restricts the scope of the rule. Although the field is optional, almost all deny-others rules will need to be restricted by protocol. There are two reasons for this:

  • Not all IP protocols support the concept of ports. Rules that use destination-port or source-port need to use ‘within’ to restrict the rule scope to IP protocols that support ports (e.g. TCP, UDP).
  • Many users are focused on TCP, UDP access policy and are not prepared to establish policy for other IP protocols.

When reasoning about deny-others rules it can be helpful to treat the rule as a boolean expression:

IF traffic matches the network section

AND traffic matches the ‘within’ section

AND traffic is NOT in the ‘deny-all-except’ list

THEN the traffic is in violation of the rule.

Example:

access-policy:
  - name: dmz-ingress
    comment: example
    owner: example@example.com
    ingress-network: DMZ
    rules:
      - type: ingress-deny-others
        comment: Limit SSH access to only from bastion network
        within:
          - protocol: TCP
            destination-port: SSH
        deny-all-except:
            flows:
                - comment: Internal SSH access
                  source-address: BASTION
                  destination-port: SSH
                  protocol: TCP

egress-deny-others

Identical to ingress-deny-others. Asserts that traffic can never be successfully delivered to the target network except for specific permitted flows. This rule looks for any possible way a forbidden packet could be successfully delivered.

See ingress-deny-others for more information.

Example:

access-policy:
  - name: client-egress
    comment: |
        This policy asserts that traffic entering the CLIENT_BORDER interfaces can reach
        only necessary resources on the network. It targets the CLIENT_BORDER interfaces
        directly to ensure the policy applies even to spoofed source addresses.
    owner: example@example.com
    egress-network:
        enter-interface: CLIENT_BORDER
    rules:
      - type: ingress-deny-others
        comment: Limit TCP/UDP access to DMZ network, external only
        within:
          - protocol: TCP UDP
        deny-all-except:
            flows:
                - comment: Client - DMZ
                  destination-address: DMZ
                  destination-port: HTTP HTTPS SSH
                - comment: Client - NTP
                  destination-address: NTP
                  destination-port: NTP
                - comment: Client - DNS
                  destination-address: DNS
                  destination-port: DNS
                - comment: Client - External
                  destination-exclude: RFC1918 DMZ