239 lines
7.7 KiB
Python
239 lines
7.7 KiB
Python
#!/usr/bin/python
|
|
#
|
|
# Copyright: Ansible Project
|
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
|
|
from __future__ import absolute_import, division, print_function
|
|
|
|
__metaclass__ = type
|
|
|
|
|
|
DOCUMENTATION = """
|
|
module: asa_acl
|
|
author: Patrick Ogenstad (@ogenstad)
|
|
short_description: (deprecated, removed after 2022-06-01) Manage access-lists on a
|
|
Cisco ASA
|
|
description:
|
|
- This module allows you to work with access-lists on a Cisco ASA device.
|
|
version_added: 1.0.0
|
|
deprecated:
|
|
alternative: asa_acls
|
|
why: Newer and updated modules released with more functionality in Ansible 2.10
|
|
removed_at_date: '2022-06-01'
|
|
extends_documentation_fragment:
|
|
- cisco.asa.asa
|
|
options:
|
|
lines:
|
|
description:
|
|
- The ordered set of commands that should be configured in the section. The commands
|
|
must be the exact same commands as found in the device running-config. Be sure
|
|
to note the configuration command syntax as some commands are automatically
|
|
modified by the device config parser.
|
|
required: true
|
|
aliases:
|
|
- commands
|
|
type: list
|
|
elements: str
|
|
before:
|
|
description:
|
|
- The ordered set of commands to push on to the command stack if a change needs
|
|
to be made. This allows the playbook designer the opportunity to perform configuration
|
|
commands prior to pushing any changes without affecting how the set of commands
|
|
are matched against the system.
|
|
type: list
|
|
elements: str
|
|
after:
|
|
description:
|
|
- The ordered set of commands to append to the end of the command stack if a changed
|
|
needs to be made. Just like with I(before) this allows the playbook designer
|
|
to append a set of commands to be executed after the command set.
|
|
type: list
|
|
elements: str
|
|
match:
|
|
description:
|
|
- Instructs the module on the way to perform the matching of the set of commands
|
|
against the current device config. If match is set to I(line), commands are
|
|
matched line by line. If match is set to I(strict), command lines are matched
|
|
with respect to position. Finally if match is set to I(exact), command lines
|
|
must be an equal match.
|
|
default: line
|
|
choices:
|
|
- line
|
|
- strict
|
|
- exact
|
|
type: str
|
|
replace:
|
|
description:
|
|
- Instructs the module on the way to perform the configuration on the device. If
|
|
the replace argument is set to I(line) then the modified lines are pushed to
|
|
the device in configuration mode. If the replace argument is set to I(block)
|
|
then the entire command block is pushed to the device in configuration mode
|
|
if any line is not correct.
|
|
default: line
|
|
choices:
|
|
- line
|
|
- block
|
|
type: str
|
|
force:
|
|
description:
|
|
- The force argument instructs the module to not consider the current devices
|
|
running-config. When set to true, this will cause the module to push the contents
|
|
of I(src) into the device without first checking if already configured.
|
|
type: bool
|
|
default: no
|
|
config:
|
|
description:
|
|
- The module, by default, will connect to the remote device and retrieve the current
|
|
running-config to use as a base for comparing against the contents of source. There
|
|
are times when it is not desirable to have the task get the current running-config
|
|
for every task in a playbook. The I(config) argument allows the implementer
|
|
to pass in the configuration to use as the base config for comparison.
|
|
type: str
|
|
"""
|
|
|
|
EXAMPLES = """
|
|
- cisco.asa.asa_acl:
|
|
lines:
|
|
- access-list ACL-ANSIBLE extended permit tcp any any eq 82
|
|
- access-list ACL-ANSIBLE extended permit tcp any any eq www
|
|
- access-list ACL-ANSIBLE extended permit tcp any any eq 97
|
|
- access-list ACL-ANSIBLE extended permit tcp any any eq 98
|
|
- access-list ACL-ANSIBLE extended permit tcp any any eq 99
|
|
before: clear configure access-list ACL-ANSIBLE
|
|
match: strict
|
|
replace: block
|
|
provider: '{{ cli }}'
|
|
|
|
- cisco.asa.asa_acl:
|
|
lines:
|
|
- access-list ACL-OUTSIDE extended permit tcp any any eq www
|
|
- access-list ACL-OUTSIDE extended permit tcp any any eq https
|
|
context: customer_a
|
|
provider: '{{ cli }}'
|
|
"""
|
|
|
|
RETURN = """
|
|
updates:
|
|
description: The set of commands that will be pushed to the remote device
|
|
returned: always
|
|
type: list
|
|
sample: ['access-list ACL-OUTSIDE extended permit tcp any any eq www']
|
|
"""
|
|
from ansible.module_utils.basic import AnsibleModule
|
|
from ansible_collections.cisco.asa.plugins.module_utils.network.asa.asa import (
|
|
asa_argument_spec,
|
|
)
|
|
from ansible_collections.cisco.asa.plugins.module_utils.network.asa.asa import (
|
|
get_config,
|
|
load_config,
|
|
)
|
|
|
|
from ansible_collections.ansible.netcommon.plugins.module_utils.network.common.config import (
|
|
NetworkConfig,
|
|
dumps,
|
|
)
|
|
|
|
|
|
def get_acl_config(module, acl_name):
|
|
contents = module.params["config"]
|
|
if not contents:
|
|
contents = get_config(module)
|
|
|
|
filtered_config = list()
|
|
for item in contents.split("\n"):
|
|
if item.startswith("access-list %s " % acl_name):
|
|
filtered_config.append(item)
|
|
|
|
return NetworkConfig(indent=1, contents="\n".join(filtered_config))
|
|
|
|
|
|
def parse_acl_name(module):
|
|
first_line = True
|
|
for line in module.params["lines"]:
|
|
ace = line.split()
|
|
if ace[0] != "access-list":
|
|
module.fail_json(
|
|
msg='All lines/commands must begin with "access-list" %s is not permitted'
|
|
% ace[0]
|
|
)
|
|
if len(ace) <= 1:
|
|
module.fail_json(
|
|
msg="All lines/commands must contain the name of the access-list"
|
|
)
|
|
if first_line:
|
|
acl_name = ace[1]
|
|
else:
|
|
if acl_name != ace[1]:
|
|
module.fail_json(
|
|
msg="All lines/commands must use the same access-list %s is not %s"
|
|
% (ace[1], acl_name)
|
|
)
|
|
first_line = False
|
|
|
|
return acl_name
|
|
|
|
|
|
def main():
|
|
|
|
argument_spec = dict(
|
|
lines=dict(
|
|
aliases=["commands"], required=True, type="list", elements="str"
|
|
),
|
|
before=dict(type="list", elements="str"),
|
|
after=dict(type="list", elements="str"),
|
|
match=dict(
|
|
default="line", choices=["line", "strict", "exact"], type="str"
|
|
),
|
|
replace=dict(default="line", choices=["line", "block"], type="str"),
|
|
force=dict(default=False, type="bool"),
|
|
config=dict(type="str"),
|
|
)
|
|
|
|
argument_spec.update(asa_argument_spec)
|
|
|
|
module = AnsibleModule(
|
|
argument_spec=argument_spec, supports_check_mode=True
|
|
)
|
|
|
|
lines = module.params["lines"]
|
|
|
|
result = {"changed": False}
|
|
if len(lines) > 0:
|
|
candidate = NetworkConfig(indent=1)
|
|
candidate.add(lines)
|
|
|
|
acl_name = parse_acl_name(module)
|
|
|
|
if not module.params["force"]:
|
|
contents = get_acl_config(module, acl_name)
|
|
config = NetworkConfig(indent=1, contents=contents)
|
|
|
|
commands = candidate.difference(config)
|
|
if commands and module.params["replace"] == "block":
|
|
commands = str(candidate).split("\n")
|
|
else:
|
|
commands = dumps(commands, "commands").split("\n")
|
|
commands = [str(c) for c in commands if c]
|
|
else:
|
|
commands = str(candidate).split("\n")
|
|
|
|
if commands:
|
|
if module.params["before"]:
|
|
commands[:0] = module.params["before"]
|
|
|
|
if module.params["after"]:
|
|
commands.extend(module.params["after"])
|
|
|
|
if not module.check_mode:
|
|
load_config(module, commands)
|
|
|
|
result["changed"] = True
|
|
|
|
result["updates"] = commands
|
|
|
|
module.exit_json(**result)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|