diff --git a/README.md b/README.md index fd2272b..349b1e7 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,160 @@ -# ansible-role-dellos-acl -The dellos-acl facilitates the configuration of access control list (ACL) attributes in devices running Dell EMC Networking Operating Systems. +ACL Role for Dell EMC Networking OS +====================================== + +This role facilitates the configuration of an access control list (ACL). It supports the configuration of different types of ACLs (standard and extended) for both IPv4 and IPv6, and assigns the access-class to the line terminals. This role is abstracted for Dell EMC Networking OS9. + + +Installation +------------ + +``` +ansible-galaxy install Dell-Networking.dellos-acl +``` + +Requirements +------------ +This role requires an SSH connection for connectivity to your Dell EMC Networking device. You can use any of the built-in OS connection variables or the ``provider`` dictionary. + +Role Variables +-------------- + +``dellos_acl``(dictionary) contains the hostname (dictionary). The hostname is the value of the ``hostname`` variable that corresponds to the name of the OS device. This role is abstracted using the ``ansible_net_os_name`` variable that can take the following value "dellos9". + +Any role variable with a corresponding state variable set to absent negates the configuration of that variable. For variables with no state variable, setting an empty value for the variable negates the corresponding configuration. The variables and its values are case-sensitive. + +``hostname`` contains the following keys: + +| Key | Type | Notes | +|------------|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| type | string (required) choices: ipv4, ipv6, mac | Configures the L3 (IPv4/IPv6) or L2 (MAC) access control list. | +|name| string (required) | Configures the name of the access control list. | +|description| string | Configures the description about the access control list. | +|isextended| boolean: true, false | If set to true, configures extended type ACL; if set to false, configures standard ACL. This variable is not supported for IPv6. | +| seqlist | list | Configures rules in the access control list. See the following seqlist.* keys for each list item. | +| seqlist.number | int (required) | Specifies the sequence number of the rule in access control list. | +|seqlist.ispermit| boolean (required): true, false | If set to true, specifies the rule to permit packets; if set to false, specifies to reject packets. | +|seqlist.protocol| string (required) | Specifies the type of protocol or the protocol number to filter. | +|seqlist.source| string (required) | Specifies the source address to match in the packets. | +|seqlist.src_condition| string | Specifies the condition to filter packets from the source address. This key is ignored when the type is MAC. | +|seqlist.destination| string (required) | Specifies the destination address to match in the packets. | +|seqlist.dest_condition| string | Specifies the condition to filter packets to the destination address. | +|seqlist.state | string, choices: absent, present* | If set to absent, deletes the rule from the access control list. | +|ingress_intf | list | Configures ingress ACL to the interface. See the following ingress_intf.* keys for each list item. | +| ingress_intf.name | string (required) | Configures the ingress ACL filter to the interface with this interface name. | +| ingress_intf.state | string, choices: absent, present* | If set to absent, deletes the configured ACL from the interface. | +|egress_intf | list | Configures egress ACL to the interface. See the following egress_intf.* keys for each list item. | +| egress_intf.name | string (required) | Configures the egress ACL filter to the interface with this interface name. | +| egress_intf.state | string, choices: absent, present* | If set to absent, deletes the configured egress ACL from the interface. | +| lineterminal | list | Configures the terminal to apply the access control list. See the following lineterminal.* keys for each list item. | +| lineterminal.line | string (required) | Configures access class on the line terminal. | +| lineterminal.state | string, choices: absent, present* | If set to absent, deletes the access class from line terminal. | +| state | string, choices: absent, present* | If set to absent, deletes the access control list. | + +``` +Note: Asterisk (*) denotes the default value if none is specified. +``` + +Connection Variables +-------------------- + +Ansible Dell EMC Networking roles require the following connection information to establish communication with the nodes in your inventory. This information can exist in the Ansible group_vars or host_vars directories, or in the playbook itself. + + + +| Key | Required | Choices | Description | +| ----------: | -------- | ---------- | ---------------------------------------- | +| host | yes | | Hostname or address for connecting to the remote device over the specified ``transport`` variable. The value of this key is the destination address for the transport. | +| port | no | | Port used to build the connection to the remote device. If the value of this key is unspecified, the value defaults to 22. | +| username | no | | Configures the username that authenticates the connection to the remote device. The value of this key authenticates the CLI login. If this key does not specify a value, the value of environment variable ANSIBLE_NET_USERNAME is used instead. | +| password | no | | Specifies the password that authenticates the connection to the remote device. If this key does not specify a value, the value of environment variable ANSIBLE_NET_PASSWORD is used instead. | +| authorize | no | yes, no* | Instructs the module to enter privileged mode on the remote device before sending any commands. If this key does not specify a value, the value of environment variable ANSIBLE_NET_AUTHORIZE is used instead. If not specified, the device attempts to execute all commands in non-privileged mode.| +| auth_pass | no | | Specifies the password to use if required to enter privileged mode on the remote device. If ``authorize`` is set to no, then this key is not applicable. If this key does not specify a value, the value of environment variable ANSIBLE_NET_AUTH_PASS is used instead. | +| transport | yes | cli* | Configures the transport connection to use when connecting to the remote device. This key supports connectivity to the device over CLI (SSH). | +| provider | no | | Convenient method that passes all of the above connection arguments as a dictionary object. All constraints (such as required or choices) must be met either by individual arguments or values in this dictionary. | + + +``` +Note: Asterisk (*) denotes the default value if none is specified. +``` + +Dependencies +------------ + +The dellos-acl role is built on modules included in the core Ansible code. These modules were added in Ansible version 2.2.0. + +Example Playbook +---------------- + +The following example uses the dellos-acl role to configure different types of ACLs (standard and extended) for both IPv4 and IPv6 and assigns the access-class to the line terminals. The example creates a ``hosts`` file with the switch details and corresponding variables defined in the ``vars/main.yaml`` file at the role path. It writes a simple playbook that only references the dellos-acl role. + +Sample ``hosts`` file: + + leaf1 ansible_host= ansible_net_os_name= + +Sample ``host_vars/leaf1``: + + hostname: leaf1 + provider: + host: "{{ hostname }}" + username: xxxxx + password: xxxxx + authorize: yes + auth_pass: xxxxx + transport: cli + +Sample ``vars/main.yaml``: + + dellos_system: + leaf1: + - type: ipv4 + name: ssh-only + description: ipv4acl + isextended: true + seqlist: + - number: 5 + ispermit: true + protocol: tcp + source: any + src_condition: ack + destination: any + dest_condition: eq 22 + state: present + ingress_intf: + - name: fortyGigE 1/28 + state: present + egress_intf: + - name: fortyGigE 1/28 + state: present + lineterminal: + - line: vty 1 + state: present + - line: vty 2 + state: absent + state: present + +Simple playbook to setup system, ``leaf.yaml``: + + - hosts: leaf1 + roles: + - Dell-Networking.dellos-acl + +Then run with: + + ansible-playbook -i hosts leaf.yaml + +License +------- + +Copyright (c) 2017, Dell Inc. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..5d953ac --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,2 @@ +--- +# defaults file for Dell-Networking.dellos-acl \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..ccd07b9 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for Dell-Networking.dellos-acl \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..8db9937 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,17 @@ +# Copyright (c) 2017 Dell Inc. +--- +galaxy_info: + author: Dell EMC Networking Engineering + description: The dellos-acl facilitates the configuration of access control list (ACL) attributes in devices running Dell EMC Networking Operating Systems. + license: Apache 2.0 + min_ansible_version: 2.2 + + platforms: + - name: Dell OS9 + + galaxy_tags: + - Networking + - Dell + - EMC + - OS9 + - DellEMC diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..8e4cd92 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,9 @@ +--- +# tasks file for Dell-Networking.dellos-acl + - name: "Provision acl configuration for OS9" + dellos9_config: + src: dellos9_acl.j2 + provider: "{{ cli }}" + when: ansible_net_os_name == "dellos9" +# notify: save config os9 + register: output diff --git a/templates/dellos9_acl.j2 b/templates/dellos9_acl.j2 new file mode 100644 index 0000000..2d155b6 --- /dev/null +++ b/templates/dellos9_acl.j2 @@ -0,0 +1,235 @@ +#jinja2: trim_blocks: True,lstrip_blocks: True +{#################################### + +Purpose: +Configure acl on OS9 devices + +dellos_acl: + leaf3: + - name: ssh-only + type: ipv4 + description: acl + isextended: true + seqlist: + - number: 10 + ispermit: true + protocol: tcp + source: any + destination: any + src_condition: eq 22 + dest_condition: ack + state: present + ingress_intf: + - name: fortyGigE 1/8 + state: present + - name: fortyGigE 1/9 + state: present + egress_intf: + - name: fortyGigE 1/19 + state: present + lineterminal: + - line: vty 0 + state: present + - line: vty 1 + state: present + state: present + - name: ipv6-ssh-only + type: ipv6 + seqlist: + - number: 10 + ispermit: true + protocol: ipv6 + source: 2001:4898::/32 + destination: any + - number: 20 + ispermit: true + protocol: tcp + source: any + src_condition: ack + destination: any + - number: 40 + ispermit: true + protocol: tcp + source: any + destination: any + state: present + lineterminal: + - line: vty 0 + state: present + - line: vty 1 + state: present +#####################################} +{% if (dellos_acl is defined and dellos_acl) and (hostname in dellos_acl) %} +{% set acl_vars = dellos_acl[hostname] %} + + {% for val in acl_vars %} + {% if val.name is defined and val.name %} + {% if val.state is defined and val.state == "absent" %} + {% if val.type is defined and val.type == "ipv4" %} + {% if val.isextended is defined and val.isextended %} +no ip access-list extended {{ val.name }} + {% else %} +no ip access-list standard {{ val.name }} + {% endif %} + {% elif val.type is defined and val.type == "ipv6" %} +no ipv6 access-list {{ val.name }} + {% elif val.type is defined and val.type == "mac" %} + {% if val.isextended is defined and val.isextended %} +no mac access-list extended {{ val.name }} + {% else %} +no mac access-list standard {{ val.name }} + {% endif %} + {% endif %} + {% else %} + {% if val.type is defined and val.type == "ipv4" %} + {% if val.isextended is defined and val.isextended %} +ip access-list extended {{ val.name }} + {% else %} +ip access-list standard {{ val.name }} + {% endif %} + {% elif val.type is defined and val.type == "ipv6" %} +ipv6 access-list {{ val.name }} + {% elif val.type is defined and val.type == "mac" %} + {% if val.isextended is defined and val.isextended %} +mac access-list extended {{ val.name }} + {% else %} +mac access-list standard {{ val.name }} + {% endif %} + {% endif %} + {% if val.description is defined %} + {% if val.description %} + description {{ val.description }} + {% else %} + no description a + {% endif %} + {% endif %} + {% if val.seqlist is defined and val.seqlist %} + {% for rule in val.seqlist %} + {% if rule.number is defined and rule.number %} + {% if rule.state is defined and rule.state == "absent" %} + no seq {{ rule.number }} + {% else %} + {% if rule.ispermit is defined %} + {% if rule.ispermit %} + {% set is_permit = "permit" %} + {% else %} + {% set is_permit = "deny" %} + {% endif %} + {% if val.type is defined and val.type == "mac" %} + {% if rule.source is defined and rule.source %} + {% if rule.destination is defined and rule.destination %} + {% if rule.dest_condition is defined and rule.dest_condition %} + {% if rule.dest_condition == "log" %} + {% set dest_condition = rule.dest_condition + ' threshold-in-msgs 10 interval 5' %} + {% else %} + {% set dest_condition = rule.dest_condition %} + {% endif %} + seq {{ rule.number }} {{ is_permit }} {{ rule.source }} {{ rule.destination }} {{ dest_condition }} + {% else %} + seq {{ rule.number }} {{ is_permit }} {{ rule.source }} {{ rule.destination }} + {% endif %} + {% endif %} + {% endif %} + {% else %} + {% if rule.protocol is defined and rule.protocol %} + {% if rule.source is defined and rule.source %} + {% if rule.destination is defined and rule.destination %} + {% if rule.source_condition is defined and rule.source_condition %} + {% if rule.dest_condition is defined and rule.dest_condition %} + {% if rule.dest_condition == "log" %} + {% set dest_condition = rule.dest_condition + ' threshold-in-msgs 10 interval 5' %} + {% else %} + {% set dest_condition = rule.dest_condition %} + {% endif %} + seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.src_condition }} {{ rule.destination }} {{ dest_condition }} + {% else %} + seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.src_condition }} {{ rule.destination }} + {% endif %} + {% else %} + {% if rule.dest_condition is defined and rule.dest_condition %} + {% if rule.dest_condition == "log" %} + {% set dest_condition = rule.dest_condition + ' threshold-in-msgs 10 interval 5' %} + {% else %} + {% set dest_condition = rule.dest_condition %} + {% endif %} + seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }} {{ dest_condition }} + {% else %} + seq {{ rule.number }} {{ is_permit }} {{ rule.protocol }} {{ rule.source }} {{ rule.destination }} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + + {% if val.lineterminal is defined and val.lineterminal %} + {% if val.type is defined and not val.type == "mac" %} + {% for vty in val.lineterminal %} + {% if vty.line is defined and vty.line %} +line {{ vty.line }} + {% if vty.state is defined and vty.state == "absent" %} + no access-class {{ val.name }} {{ val.type }} + {% else %} + access-class {{ val.name }} {{ val.type }} + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + {% endif %} + + {% if val.ingress_intf is defined and val.ingress_intf %} + {% for intf in val.ingress_intf %} + {% if intf.state is defined and intf.state == "absent" %} + {% if intf.name is defined and intf.name %} +interface {{ intf.name }} + {% if val.type is defined and val.type == "mac" %} + no mac access-group {{ val.name }} in + {% else %} + no ip access-group {{ val.name }} in + {% endif %} + {% endif %} + {% else %} + {% if intf.name is defined and intf.name %} +interface {{ intf.name }} + {% if val.type is defined and val.type == "mac" %} + mac access-group {{ val.name }} in + {% else %} + ip access-group {{ val.name }} in + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + + {% if val.egress_intf is defined and val.egress_intf %} + {% for intf in val.egress_intf %} + {% if intf.state is defined and intf.state == "absent" %} + {% if intf.name is defined and intf.name %} +interface {{ intf.name }} + {% if val.type is defined and val.type == "mac" %} + no mac access-group {{ val.name }} out + {% else %} + no ip access-group {{ val.name }} out + {% endif %} + {% endif %} + {% else %} + {% if intf.name is defined and intf.name %} +interface {{ intf.name }} + {% if val.type is defined and val.type == "mac" %} + mac access-group {{ val.name }} out + {% else %} + ip access-group {{ val.name }} out + {% endif %} + {% endif %} + {% endif %} + {% endfor %} + {% endif %} + {% endif %} + {% endif %} + {% endfor %} +{% endif %} diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/tests/main.yml b/tests/main.yml new file mode 100644 index 0000000..8919ef0 --- /dev/null +++ b/tests/main.yml @@ -0,0 +1,81 @@ +--- +# vars file for Dell-Networking.dellos-acl, below gives a sample configuration + +dellos_acl: + leaf3: + - name: ssh-only-mac + type: mac + description: macacl + isextended: true + seqlist: + - number: 5 + ispermit: true + protocol: tcp + source: any + destination: any + dest_condition: log + state: present + - number: 6 + ispermit: false + protocol: tcp + source: bb:bb:bb:bb:bb:bb aa:aa:aa:aa:aa:aa + destination: any + dest_condition: log + state: present + ingress_intf: + - name: fortyGigE 1/28 + state: present + - name: fortyGigE 1/27 + state: present + egress_intf: + - name: fortyGigE 1/28 + state: present + lineterminal: + - line: vty 1 + state: present + - line: vty 2 + state: absent + - line: vty 3 + state: present + - name: ipv6-ssh-only + type: ipv6 + description: ipv6acl + seqlist: + - number: 10 + ispermit: true + protocol: ipv6 + source: 2001:4898::/32 + destination: any + - number: 20 + ispermit: true + protocol: tcp + source: any + src_condition: ack + destination: 2404:f801::/32 + - number: 30 + ispermit: true + protocol: tcp + source: any + destination: 2a01:110::/31 + dest_condition: ack + - number: 40 + ispermit: true + protocol: tcp + source: any + destination: any + ingress_intf: + - name: fortyGigE 1/26 + state: present + - name: fortyGigE 1/27 + state: present + egress_intf: + - name: fortyGigE 1/26 + state: present + lineterminal: + - line: vty 0 + state: absent + - line: vty 1 + - line: vty 2 + - line: vty 3 + state: present + diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..cdf43f6 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,5 @@ +--- +- hosts: localhost + remote_user: root + roles: + - Dell-Networking.dellos-acl \ No newline at end of file diff --git a/vars/main.yml b/vars/main.yml new file mode 100644 index 0000000..c7d25c2 --- /dev/null +++ b/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for Dell-Networking.dellos-acl