Firewall access rule

You can create, modify, or delete firewall access rules in the SMC. Rules can also be fetched in various ways outlined in the documentation below.

Creating, modifying or deleting firewall rules

You can create, modify, or delete firewall access rules based on the playbook configuration. See the sections below for details about each operation type.

Creating a rule

Creating a rule requires basic information as documented by the Firewall Rule module.

An operation will be considered a ‘create’ if the playbook definition does not provide the ‘tag’ attribute. The ‘tag’ attribute is a unique identifier for an existing rule that uniquely identifies the rule because rule names can be identical. Therefore, if a rule definition in a playbook has the tag attribute, it will be considered a ‘modify’ operation.

Note

The ‘tag’ field of an existing rule is ‘read-only’ and only uniquely identifies the rule. It does not specify the rule position in a rule set.

Setting ‘present’ on the playbook state attribute is required to create or modify a rule. If the state is absent, the operation will be considered a delete operation and will use the rule tag identifier to find the correct rule.

Basic rule creation

in this simple example of creating a rule, only the name field is provided. If sources, destinations or services are not provided, the default value is ‘any’. If action is not provided, the default setting is ‘allow’:

- name:
  hosts: localhost
  gather_facts: no
  tasks:
  - name: Task output
    firewall_rule:
      policy: TestPolicy
      rules:
      -   name: foo

You can create much more detailed rules by using other options within the firewall access rule module.

Creating more detailed rules

An example of creating a basic continue rule that allows all logging at the beginning of a policy:

- name: Task output
  register: result
  firewall_rule:
    policy: TestPolicy
    rules:
    -   action: continue
        comment: logging rule
        log_options:
          log_accounting_info_mode: true
          log_closing_mode: true
          log_level: stored
        is_disabled: false
        name: Log all continue rule

However, there are many more options available to create a rule, including setting connection tracking settings, inspection features, mss settings, and additional log settings. It is also possible to specify elaborate rules based on sources, destinations and services. Rule actions such as use_vpn, forward_vpn and apply_vpn, and jump_rules are supported.

Generally it is easier to retrieve an existing rule and dump to YAML, then make modifications to suit your requirements. See Finding Firewall Rules for more information about retrieving existing rules.

Customize all rule fields

An example of creating a rule with specific destinations and service elements. All source, destination and service elements are documented in the firewall_rule module. Elements can also be retrieved or created using the Network Elements module.

Note

Source, destination, and service elements are validated before any operations are performed to modify or create an element. The playbook run will fail on missing elements.

- name:
  hosts: localhost
  gather_facts: no
  tasks:
  - name: Task output
    firewall_rule:
      policy: TestPolicy
      rules:
      -   action: allow
          comment: my comment
          connection_tracking:
              mss_enforced: true
              mss_enforced_max: 1555
              mss_enforced_min: 0
              timeout: 10
              state: normal
          destinations:
              group:
              - foogroup
              ip_list:
              - Amazon S3
              host:
              - host-1.1.1.1
              network:
              - foonet
          inspection_options:
              decrypting: null
              deep_inspection: null
              file_filtering: null
          is_disabled: false
          log_options:
              application_logging: enforced
              eia_executable_logging: 'off'
              log_accounting_info_mode: false
              log_closing_mode: true
              log_compression: 'off'
              log_level: none
              log_payload_additionnal: true
              log_payload_excerpt: false
              log_payload_record: false
              log_severity: -1
              user_logging: enforced
          authentication_options:
             methods: []
             require_auth: false
          name: ruletest2
          services:
              tcp_service:
              - AOL
              udp_service:
              - Biff
              ip_service:
              - CHAOS
          sources:
              engine:
              - myfw
              alias:
              - $$ Interface ID 0.ip
              country:
              - China

Creating rules with authentication

Rules can be created that specify authentication by setting the authentication_options dict on the rule. When enabling authentication, you must provide the authentication method along with at least one reference to a user or group from an internal user domain or an external LDAP domain.

You must specify the user or group information in full distinguished name (DN) syntax because this is how users and groups are identified within the SMC.

A simple example YAML for authentication might look like:

authentication_options:
   groups:
   - dc=pages,dc=local,domain=myldapdomain
   methods:
   - LDAP Authentication
   - Network Policy Server
   - User password
   require_auth: true
   users:
   - cn=test,dc=stonegate,domain=InternalDomain
   - cn=test2,dc=stonegate,domain=InternalDomain

This example specifies that auth is required and several authentication methods are supported. In addition, two internal users and one external LDAP domain are allowed to authenticate (using the LDAP domain’s base DN).

Creating VPN rules

An example of creating an ‘enforce_vpn’ rule requires the use of the parameter vpn_policy along with one of the valid VPN actions. In addition, the rule specifies a valid authentication service, sets require_auth to true and defines the base DN of the domain to allow authentication:

- name: Task output
  register: result
  firewall_rule:
    smc_logging:
      level: 10
      path: ansible-smc.log
    policy: TestPolicy
    rules:
    -   action: enforce_vpn
        comment: my comment
        connection_tracking:
            mss_enforced: false
            mss_enforced_max: -1
            mss_enforced_min: -1
            timeout: -1
        destinations:
            any: true
        inspection_options:
            decrypting: true
            deep_inspection: true
            file_filtering: null
        is_disabled: false
        authentication_options:
            methods:
            - LDAP Authentication
            require_auth: true
            groups:
            - dc=pages,dc=local,domain=myldapdomain
            users:
            - cn=myuser,dc=stonegate,domain=InternalDomain
        log_options:
            application_logging: default
            eia_executable_logging: default
            log_accounting_info_mode: true
            log_closing_mode: false
            log_compression: 'off'
            log_level: stored
            log_payload_additionnal: false
            log_payload_excerpt: false
            log_payload_record: false
            log_severity: -1
        name: ruletest2
        services:
            any: true
        sources:
            any: true
        vpn_policy: MOBILE CLIENT VPN

Creating jump rules

An example of creating a ‘jump’ rule requires the use of the parameter sub_policy along with the action of jump:

- name: Task output
  register: result
  firewall_rule:
    smc_logging:
      level: 10
      path: ansible-smc.log
    policy: TestPolicy
    rules:
    -   action: jump
        comment: my comment
        connection_tracking:
            mss_enforced: false
            mss_enforced_max: -1
            mss_enforced_min: -1
            timeout: -1
        destinations:
            any: true
        inspection_options:
            decrypting: null
            deep_inspection: null
            file_filtering: null
        is_disabled: false
        authentication_options:
             methods: []
             require_auth: false
             users: []
        log_options:
            application_logging: enforced
            eia_executable_logging: default
            log_accounting_info_mode: true
            log_closing_mode: false
            log_compression: 'off'
            log_level: stored
            log_payload_additionnal: false
            log_payload_excerpt: true
            log_payload_record: false
            log_severity: -1
            user_logging: 'true'
        name: ruletest2
        services:
            any: true
        sources:
            any: true
        sub_policy: mysubpolicy

Inserting rules in a specific position

It is also possible to add a rule after or before another specified rule using the target rule’s tag field. It is recommended that when you want to insert rules in a specific position, you locate the rule to insert ‘before’ or ‘after’ and specify that rule tag in the rule YAML. When rules are added, without specifying a position, they will be added in position #1 (at the top of the policy).

Using that logic, if you have multiple rules that should all be inserted in a specific order somewhere in the rule list, one strategy is to fetch the existing policy to locate the rule tag that will act as the insert point. Then, list your rules in the YAML from lowest in the list to highest, with all rules using the same add_after rule tag.

This example shows inserting a deny all rule after rule with a specific tag:

Note

By default, rules are always inserted at the top of the policy unless specified otherwise

- name: Add a deny rule after specified rule using add_after syntax
 register: result
 firewall_rule:
   smc_logging:
     level: 10
     path: ansible-smc.log
   policy: TestPolicy
   rules:
   -   action: discard
       comment: deny rule
       is_disabled: false
       name: my deny
       add_after: '2097193.0'

Note

You can leave fields like log_options, inspection_options and connection_tracking out of the playbook run if there is no need to customize those settings.

More examples can be found in the playbooks directory.

Modifying a rule

Modifying a rule consists of first retrieving the rule, making modifications, and re-running the playbook. Retrieving the rule can be done using the techniques describes below in Finding Firewall Rules.

After you have retrieved the rule, you will notice a ‘tag’ field. The tag is a unique identifier for each rule. Rule names are not unique and rules can have the same rule name. When a playbook is run on a rule that has a ‘tag’ value, the operation will be considered a modify operation.

To modify rules, after the rule has been retrieved, the content will look similar to the following:

- name: Task output
  register: result
  firewall_rule:
    smc_logging:
      level: 10
      path: ansible-smc.log
    policy: TestPolicy
    rules:
    -   action: continue
        comment: null
        connection_tracking:
            mss_enforced: false
            mss_enforced_max: 0
            mss_enforced_min: 0
            timeout: -1
        destinations:
            any: true
        inspection_options:
            decrypting: null
            deep_inspection: null
            file_filtering: null
        is_disabled: false
        log_options:
            log_accounting_info_mode: false
            log_closing_mode: true
            log_level: undefined
            log_payload_additionnal: false
            log_payload_excerpt: false
            log_payload_record: false
            log_severity: -1
        name: Rule @2097166.2
        services:
            any: true
        sources:
            any: true
        tag: '2097166.2'

When modifying rules you can also move a rule by using the add_after or add_before fields. For these fields to work, you must provide the ‘tag’ for the rule you want to move the rule ‘before’ or ‘after’. This will result in the rule being duplicated into the correct position and the original rule being removed.

Note

This will be a no-op if the rule could not be found based on the rule tag value provided. In addition, this will change the rule tag of the original rule so a refetch will be necessary to operate on the rule again.

An example of modifying a rule and moving it into a new position:

- name:
  hosts: localhost
  gather_facts: no
  tasks:
  - name: Task output
    register: result
    firewall_rule:
      policy: TestPolicy
      rules:
      -   action: allow
          destinations:
              host:
              - host-2.2.2.5
              network:
              - gateway_170.27.126.0/24
          is_disabled: false
          name: newruleinpos
          services:
              any: true
          sources:
              any: true
          tag: '2097164.19'
          add_after: '2097260.0'

See Exporting a Firewall Rule into YAML for more information about retrieving existing rules.

Deleting a rule

Deleting a firewall access rule can be done by setting state=absent on the playbook. You must also pre-fetch the rule in order to validate deleting the correct rule. Rules are identified by the ‘tag’ attribute returned after fetching the rule because rule names are not unique.

Example of deleting a rule by rule tag after fetching (and removing other unneeded attributes):

- name: Task output
  firewall_rule:
    policy: TestPolicy
    rules:
    -   tag: '2097203.0'
    state: absent

Generally you might want to search for the particular rule of interest using firewall_rule_facts to narrow the search, return the results in yaml and delete.

Finding firewall access rules

You can obtain facts about firewall access rules by providing various filters for retrieving data.

The filter parameter is always required when obtaining rules, with filter specifying the Firewall Policy from which to retrieve the rules from.

There are varying details and options for retrieving rules. These are outlined in the next section.

Retrieving only name and rule position (metadata):

Retrieving metadata is done by providing only a filter that specifies the firewall policy. All rules are returned with only metadata.

- name: Rule tasks
  hosts: localhost
  gather_facts: no
  tasks:
  - name: Show rules for policy 'TestPolicy' (only shows name, type)
    firewall_rule_facts:
      filter: TestPolicy

This search results in the following output:

ok: [localhost] => {
   "ansible_facts": {
       "firewall_rule": [
           {
               "comment": null,
               "policy": "TestPolicy",
               "rules": [
                   {
                       "name": "Rule @2097166.2",
                       "pos": 1,
                       "type": "fw_ipv4_access_rule"
                   },
                   {
                       "name": "my@rule",
                       "pos": 2,
                       "type": "fw_ipv4_access_rule"
                   },

You can also obtain rules based a specific range of rules using the rule_range field. For example, you might want to obtain the first five rules, or rules 10-15 to limit the search.

Retrieving rule based on rule range:

- name: Get specific rules based on range order (rules 1-3)
  firewall_rule_facts:
    filter: TestPolicy
    rule_range: 1-3

This search results in the following output:

ok: [localhost] => {
   "ansible_facts": {
       "firewall_rule": [
           {
               "comment": null,
               "policy": "TestPolicy",
               "rules": [
                   {
                       "name": "Rule @2097166.2",
                       "type": "fw_ipv4_access_rule"
                   },
                   {
                       "name": "ruletest",
                       "type": "fw_ipv4_access_rule"
                   },
                   {
                       "name": "Rule @2097168.0",
                       "type": "fw_ipv4_access_rule"
                   }
               ]
           }
       ]
   }

Note

rule_range and search are mutually exclusive operations

Many times it is necessary to get more details about the rule configuration itself and you may even know the name of the rule you are looking for. If the rule name is known, you can provide the parameter search with a keyword that will be used as a wildcard to find any rules with this content in the name or comment field of a rule.

Retrieving rule based on search string:

- name: Search for specific rule/s using search value (partial searching supported)
  firewall_rule_facts:
    filter: TestPolicy
    search: rulet

Note

Searching may return multiple results

This search results in the following output:

ok: [localhost] => {
   "ansible_facts": {
       "firewall_rule": [
           {
               "comment": null,
               "policy": "TestPolicy",
               "rules": [
                   {
                       "name": "ruletest",
                       "type": "fw_ipv4_access_rule"
                   }
               ]
           }
       ]
   }

This output still only tells us that a rule was found but no details about the contents of the rule.

You can use the as_yaml parameter is available that provides the ability to ‘dump’ the contents of the rule into a format that can be re-used in a playbook or alternatively just dumped into a result register.

Retrieving more details about the rule:

Adding the as_yaml parameter to obtain more detail about a rule:

- name: Dump the results in yaml format, showing details of rule
  firewall_rule_facts:
    filter: TestPolicy
    search: rulet
    as_yaml: true

The output from the run now contains must more data and the specifics about the rule itself:

ok: [localhost] => {
   "ansible_facts": {
       "firewall_rule": [
           {
               "comment": null,
               "policy": "TestPolicy",
               "rules": [
                   {
                       "action": "allow",
                       "comment": null,
                       "connection_tracking": {
                           "mss_enforced": false,
                           "mss_enforced_max": 0,
                           "mss_enforced_min": 0,
                           "state": "no",
                           "timeout": -1
                       },
                       "destinations": [
                           "https://1.1.1.1:8082/6.4/elements/host/942",
                           "https://1.1.1.1:8082/6.4/elements/host/944",
                           "https://1.1.1.1:8082/6.4/elements/host/948",
                           "https://1.1.1.1:8082/6.4/elements/network/3969"
                       ],
                       "inspection_options": {
                           "decryption": false,
                           "deep_inspection": false,
                           "file_filtering": false
                       },
                       "is_disabled": false,
                       "logging": {
                           "application_logging": "enforced",
                           "eia_executable_logging": "off",
                           "log_accounting_info_mode": true,
                           "log_closing_mode": false,
                           "log_compression": "off",
                           "log_level": "stored",
                           "log_payload_additionnal": false,
                           "log_payload_excerpt": false,
                           "log_payload_record": false,
                           "log_severity": -1,
                           "user_logging": "enforced"
                       },
                       "name": "ruletest",
                       "services": [
                           "https://1.1.1.1:8082/6.4/elements/ip_service/58",
                           "https://1.1.1.1:8082/6.4/elements/icmp_service/312",
                           "https://1.1.1.1:8082/6.4/elements/tcp_service/358",
                           "https://1.1.1.1:8082/6.4/elements/tcp_service/468",
                           "https://1.1.1.1:8082/6.4/elements/udp_service/541",
                           "https://1.1.1.1:8082/6.4/elements/udp_service/551"
                       ],
                       "sources": {
                           "any": true
                       },
                       "tag": "2097164.14"
                   }
               ]
           }
       ]
   }

However, you will notice that certain fields, sources, destinations and services will contain href’s that specify the location of the element but not the actual element itself by type or name. To obtain the resolved information for the elements, you can alternatively provide a parameter expand, which is a list of fields to resolve into element and types.

Note

Expanding HREFs will result in a single SMC API query for each element HREF and is therefore only recommended in a limited fashion. For example, expanding all rules in a rule list of 100 rules will likely result in hundreds of queries against the SMC API. It is recommended to narrow your search before expanding fields.

Expanding href fields in a facts run:

Add the expand field list to the existing playbook to provide resolution for the fields source, destination and services:

- name: Resolve the source, destination and services fields
  firewall_rule_facts:
    filter: TestPolicy
    search: rulet
    as_yaml: true
    expand:
    - sources
    - destinations
    - services

Running this task results in the following:

ok: [localhost] => {
   "ansible_facts": {
       "firewall_rule": [
           {
               "comment": null,
               "policy": "TestPolicy",
               "rules": [
                   {
                       "action": "allow",
                       "comment": null,
                       "connection_tracking": {
                           "mss_enforced": false,
                           "mss_enforced_max": 0,
                           "mss_enforced_min": 0,
                           "state": "no",
                           "timeout": -1
                       },
                       "destinations": {
                           "host": [
                               "2.2.2.5",
                               "2.2.2.6",
                               "2.2.2.23"
                           ],
                           "network": [
                               "gateway_170.27.126.0/24"
                           ]
                       },
                       "inspection_options": {
                           "decryption": false,
                           "deep_inspection": false,
                           "file_filtering": false
                       },
                       "is_disabled": false,
                       "logging": {
                           "application_logging": "enforced",
                           "eia_executable_logging": "off",
                           "log_accounting_info_mode": true,
                           "log_closing_mode": false,
                           "log_compression": "off",
                           "log_level": "stored",
                           "log_payload_additionnal": false,
                           "log_payload_excerpt": false,
                           "log_payload_record": false,
                           "log_severity": -1,
                           "user_logging": "enforced"
                       },
                       "name": "ruletest",
                       "services": {
                           "icmp_service": [
                               "Alternate Host Address (Any Code)"
                           ],
                           "ip_service": [
                               "ARIS"
                           ],
                           "tcp_service": [
                               "CreativePartnr",
                               "CreativeServer"
                           ],
                           "udp_service": [
                               "CMIP-Manager (UDP)",
                               "CMIP Agent (UDP)"
                           ]
                       },
                       "sources": {
                           "any": true
                       },
                       "tag": "2097164.14"
                   }
               ]
           }
       ]
   }

Looking at the output, you may notice that the format of the output matches the input format that can be used to create a firewall access rule. This is a useful way to also provide modifications to an existing rule. One technique for modifying an existing rule is to fetch the rule, make modifications and re-run the playbook. To do this, there are helper jinja templates that will write the output to a specified filename and can also be added to the task.

Exporting a firewall access rule into YAML using templates:

Below is a full example that builds on the previous where you can optionally export the content into valid YML format, modify as necessary and re-run the playbook.

Templates are provided in the playbooks/templates directory.

- name: Get firewall rule as yaml
  register: results
  firewall_rule_facts:
    smc_logging:
     level: 10
     path: ansible-smc.log
    filter: TestPolicy
    search: rulet
    as_yaml: true
    expand:
    - services
    - destinations
    - sources

- name: Write the yaml using a jinja template
  template: src=templates/facts_yaml.j2 dest=./firewall_rules_test.yml
  vars:
    playbook: firewall_rule

For details about supported options for playbook runs, see the Fact and Module documentation.