深入探讨 Cisco ASA 资源模块
最近,我们发表了对应用于 Ansible 安全自动化计划目标用例的资源模块的想法。该原理在网络自动化领域广为人知,我们遵循既定路径。虽然上一篇博文涵盖了一些基本示例,但我们想展示更详细的用例以及如何使用资源模块解决这些用例。
本博文深入探讨了新的 Cisco ASA 内容集合,该集合已在上一篇文章中介绍过。我们将逐步介绍几个示例,并描述用例以及我们设想在现实世界场景中如何使用该集合。
Cisco ASA 认证内容集合:它是什么?
Cisco ASA 内容集合提供了自动化Cisco 自适应安全设备系列(简称 Cisco ASA)的方法,因此得名。凭借其在防火墙和网络安全方面的优势,它们在市场上广为人知。
该集合的目标是将 Cisco ASA 设备集成到自动化的安全工作流程中。为此,该集合提供了模块来自动化通用命令和与设备的配置交互,以及访问控制列表 (ACL) 和对象组 (OG) 的面向资源的自动化。
如何安装 Cisco ASA 认证 Ansible 内容集合
Cisco ASA 集合可在 Automation Hub(我们提供的软件即服务产品)上供 Red Hat Ansible Automation Platform 客户使用,该产品位于 cloud.redhat.com,是 Red Hat 订阅者快速查找和使用 Red Hat 及其技术合作伙伴支持的内容的地方。
完成此操作后,可以轻松安装集合
ansible-galaxy collection install cisco.asa
或者,您也可以在 Ansible Galaxy 中查找集合,这是我们用于在社区中共享内容的开源中心。
Cisco ASA 内容集合中有什么?
该 Collection 的重点在于提到的模块(以及支持它们的插件):有三个用于基本交互的模块,asa_facts、asa_cli 和 asa_config。如果您熟悉 Ansible 的其他网络和防火墙 Collection 和模块,您会认出这种模式:这三个模块提供了与网络和防火墙解决方案交互的最简单方法。使用它们,可以接收通用数据,发送任意命令和管理配置部分。
虽然这些模块已经为设备完全未自动化的环境提供了巨大的价值,但本文的重点在于 Collection 中的其他模块:资源模块 asa_ogs 和 asa_acls。作为资源模块,它们的范围有限,但使用户能够专注于特定的资源,而不会受到其他内容或配置项的干扰。由于其他 Collection 遵循相同的模式,因此它们还能够实现更简单的跨产品自动化。
如果您仔细查看,您会发现另外两个模块:asa_ogs 和 asa_acls。正如我们在关于安全自动化资源模块的第一篇博文中提到的,这些是已弃用的模块,以前用于配置 ACL 和 OG。它们已被资源模块取代。
以 Collection 的方式连接到 Cisco ASA
该 Collection 支持 network_cli 作为连接类型。结合网络操作系统 cisco.asa.asa、用户名和密码,您就可以开始了。为了快速入门,您可以简单地将这些详细信息作为清单中的变量提供。
[asa01]
host_asa.example.com
[asa01:vars]
ansible_user=admin
ansible_ssh_pass=password
ansible_become=true
ansible_become_method=ansible.netcommon.enable
ansible_become_pass=become_password
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=cisco.asa.asa
ansible_python_interpreter=python
请注意,在生产环境中,应以安全的方式支持这些变量,例如,借助 Ansible Tower 凭据。
用例:ACL
在完成所有这些设置后,我们现在准备深入了解实际的 Collection 以及如何使用它们。对于第一个用例,我们希望了解如何在 ASA 中管理 ACL。在深入研究 Ansible Playbook 示例之前,让我们快速讨论一下什么是 ASA ACL 以及自动化实践者应该注意什么。
ASA 访问列表在全局创建,然后使用 access-group “command” 应用。它们可以应用于入站或出站。用户在 Cisco ASA 防火墙上使用访问列表时,需要注意以下几点
此外,更改 ACL 可能会很快变得非常复杂。这不仅与配置本身有关,还与自动化实践者的意图有关:是否应该将新的 ACL 添加到现有配置中?或者应该替换它?合并它们又如何呢?
这些问题的答案通常取决于部署更改的环境和情况。更改 ACL 的不同方法在此处以及 Cisco ASA 内容 Collection 中被记为“状态”:部署对 ACL 的更改的不同方法。
ACLs 模块知道以下状态
- 已收集 (Gathered)
- 已合并 (Merged)
- 已覆盖 (Overridden)
- 已替换 (Replaced)
- 已删除 (Deleted)
- 已呈现 (Rendered)
- 已解析 (Parsed)
在本用例讨论中,我们将查看所有这些状态,尽管并非总是详细介绍。但是,我们将为感兴趣的读者提供完整代码列表的链接。
请注意,虽然我们通常使用网络地址作为源和目标示例,但其他值(如网络对象组)也是可能的。
状态已收集 (Gathered):使用配置数据填充清单
鉴于资源模块允许读取现有网络配置并将其转换为结构化数据模型,“已收集 (gathered)”状态等同于为此特定资源收集 Ansible 事实。如果以后应将特定的配置片段重复用作变量,这将非常有用。另一个用例是读取现有网络配置并将其存储为平面文件。此平面文件可以定期提交到 git 存储库,有效地跟踪当前配置和安全工具的更改。
为了展示如何将现有配置存储为平面文件,让我们采用以下设备配置
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_access; 2 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.2.0 255.255.255.0 192.0.3.0 255.255.255.0 eq www log default (hitcnt=0) 0xdc46eb6e
access-list test_access line 2 extended deny icmp 198.51.100.0 255.255.255.0 198.51.110.0 255.255.255.0 alternate-address log errors interval 300 (hitcnt=0) 0x68f0b1cd
access-list test_R1_traffic; 1 elements; name hash: 0x2c20a0c
access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet (hitcnt=0) 0x11821a52
为了如上所述收集和存储内容,我们需要首先从每个设备收集数据,然后创建映射我们设备的目录结构,然后将配置存储在那里,在本例中为 YAML 文件。以下 playbook 正是这样做的。请注意第一个任务中的参数 state: gathered。
---
- name: convert interface to structured data
hosts: asa
gather_facts: false
tasks:
- name: Gather facts
cisco.asa.asa_acls:
state: gathered
register: gather
- name: Create inventory directory
become: true
delegate_to: localhost
file:
path: "{{ inventory_dir }}/host_vars/{{ inventory_hostname }}"
state: directory
- name: Write each resource to a file
become: true
delegate_to: localhost
copy:
content: "{{ gather[‘gathered’][0] | to_nice_yaml }}"
dest: "{{ inventory_dir }}/host_vars/{{ inventory_hostname }}/acls.yaml"
“已收集 (gathered)”状态仅收集现有数据。与大多数其他状态相反,它不会更改任何配置。从读取初始配置中获得的结果数据结构如下所示
$ cat lab_inventory/host_vars/ciscoasa/acls.yaml
- acls:
- aces:
- destination:
address: 192.0.3.0
netmask: 255.255.255.0
port_protocol:
eq: www
grant: deny
line: 1
log: default
protocol: tcp
protocol_options:
tcp: true
source:
address: 192.0.2.0
netmask: 255.255.255.0
...
您可以在 state: gathered 参考 gist 中查看所有命令和示例输出的完整详细列表。
状态已合并 (Merged):添加/更新配置
在第一个非更改状态之后,我们现在来看一个更改目标配置的状态:“已合并 (merged)”。此状态也是任何可用资源模块的默认状态 - 因为它只是添加或更新用户提供的配置。简单明了。
例如,让我们采用以下现有设备配置
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_access; 1 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.2.0 255.255.255.0 192.0.3.0 255.255.255.0 eq www log debugging interval 300 (hitcnt=0) 0xdc46eb6e
假设我们想要部署我们作为平面文件存储在已收集示例中的配置。请注意,平面文件的内容基本上是一个名为“acls”的变量。给定此平面文件和变量名,我们可以使用以下 playbook 将配置部署到设备上
---
- name: Merged state play
hosts: cisco
gather_facts: false
collections:
- cisco.asa
tasks:
- name: Merge ACLs config with device existing ACLs config
asa_acls:
state: merged
config: "{{ acls }}"
一旦我们运行此合并 playbook,所有提供的参数都将被推送到 Cisco ASA 设备并配置。
之后,网络设备配置已更改
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
ccess-list test_access; 2 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.2.0 255.255.255.0 192.0.3.0 255.255.255.0 eq www log default (hitcnt=0) 0xdc46eb6e
access-list test_access line 2 extended deny icmp 198.51.100.0 255.255.255.0 198.51.110.0 255.255.255.0 alternate-address log errors interval 300 (hitcnt=0) 0x68f0b1cd
access-list test_R1_traffic; 1 elements; name hash: 0x2c20a0c
access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet (hitcnt=0) 0x11821a52
我们使用资源模块在 playbook 中描述的所有更改现在都已在设备配置中到位。
如果我们稍微深入研究设备输出,就会有以下观察结果
-
合并 playbook 配置了 2 个 ACL
-
- test_access,配置了 2 个访问控制条目 (ACE)
- test_R1_traffic 只有一个 ACE
-
test_access 是一个 IPV4 ACL,对于第一个 ACE,我们已将行号指定为 1,而对于第二个 ACE,我们仅指定了名称,这是唯一必需的参数。所有其他参数都是可选的,可以根据特定的 ACE 策略选择。但是请注意,如果我们希望避免 ACE 被配置为 ACL 中的最后一个,则建议配置行号。
-
test_R1_traffic 是一个 IPV6 ACL
-
由于此设备上没有任何预先存在的 ACL,因此已添加所有 playbook 配置。如果我们有任何预先存在的 ACL,并且 playbook 也具有相同的 ACL(具有不同的 ACE 或相同的 ACE 但配置不同),则合并操作将使用新提供的 ACL 配置更新现有 ACL 配置。
当我们第二次运行相应的合并 playbook 时,自动化带来的另一个好处显现出来:Ansible 的幂等性魅力就出现了!playbook 运行结果为“changed=False”,这向用户确认 playbook 中提供的所有配置已在 Cisco ASA 设备上配置。
您可以在 state: merged 参考 gist 中查看所有命令和示例输出的完整详细列表。
状态已替换 (Replaced):旧的移除,新的加入
另一种典型的情况是,当设备已使用具有现有 ACE 的 ACL 配置,并且自动化实践者想要使用一组新的 ACE 更新 ACL,同时完全丢弃所有已配置的 ACE。
在这种情况下,“已替换 (replaced)”状态是理想的选择:顾名思义,“已替换 (replaced)”状态将使用用户提供的新的 ACE 集替换 ACL 现有的 ACE。如果用户尝试配置任何尚未在设备上预先配置的新 ACL,它将充当合并状态,并且 asa_acls 模块将尝试在替换 playbook 中将用户提供的 ACL ACE 配置。
让我们采用以下初始配置
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_access; 2 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.2.0 255.255.255.0 192.0.3.0 255.255.255.0 eq www log default (hitcnt=0) 0xdc46eb6e
access-list test_access line 2 extended deny icmp 198.51.100.0 255.255.255.0 198.51.110.0 255.255.255.0 alternate-address log errors interval 300 (hitcnt=0) 0x68f0b1cd
access-list test_R1_traffic; 1 elements; name hash: 0x2c20a0c
access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet (hitcnt=0) 0x11821a52
现在我们假设我们想要配置一个名为“test_global_access”的新 ACL,并且我们想要用新的源和目标 IP 替换已经存在的“test_access”ACL 配置。我们新期望状态的相应 ACL 配置为
- acls:
- name: test_access
acl_type: extended
aces:
- grant: deny
line: 1
protocol: tcp
protocol_options:
tcp: true
source:
address: 192.0.3.0
netmask: 255.255.255.0
destination:
address: 192.0.4.0
netmask: 255.255.255.0
port_protocol:
eq: www
log: default
- name: test_global_access
acl_type: extended
aces:
- grant: deny
line: 1
protocol_options:
tcp: true
source:
address: 192.0.4.0
netmask: 255.255.255.0
port_protocol:
eq: telnet
destination:
address: 192.0.5.0
netmask: 255.255.255.0
port_protocol:
eq: www
请注意,定义再次有效地包含在变量“acls”中 - 我们可以将其作为 asa_acls 模块的“config”参数的值进行引用,就像我们在上一个示例中所做的那样。只有 state 参数的值这次不同
---
- name: Replaced state play
hosts: cisco
gather_facts: false
collections:
- cisco.asa
tasks:
- name: Replace ACLs config with device existing ACLs config
asa_acls:
state: replaced
config: "{{ acls }}"
运行 playbook 后,网络设备配置已按预期更改:旧配置已替换为新配置。在没有相应配置需要替换的情况下,添加了新的配置
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_access; 1 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.3.0 255.255.255.0 192.0.4.0 255.255.255.0 eq www log default (hitcnt=0) 0x7ab83be2
access-list test_R1_traffic; 1 elements; name hash: 0x2c20a0c
access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet (hitcnt=0) 0x11821a52
access-list test_global_access; 1 elements; name hash: 0xaa83124c
access-list test_global_access line 1 extended deny tcp 192.0.4.0 255.255.255.0 eq telnet 192.0.5.0 255.255.255.0 eq www (hitcnt=0) 0x243cead5
请注意,在本例中 ACL test_R1_traffic 未被修改或删除!
您可以在 state: replaced 参考 gist 中查看所有命令和示例输出的完整详细列表。
状态已覆盖 (Overridden):丢弃不需要的
如上一个示例中所述,定义中未明确提及的 ACL 保持不变。但是,如果需要使用输入 ACL ACE 配置重新配置所有现有和预配置的 ACL,以及影响那些未提及的 ACL 呢?这就是“已覆盖 (overridden)”状态发挥作用的地方。
如果您采用上一个示例中的相同初始环境并对它部署相同的 ACL 定义,但这次将状态切换为“已覆盖 (overridden)”,则设备的结果配置看起来大不相同
部署 ACL 之前,初始设备配置
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_access; 2 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.2.0 255.255.255.0 192.0.3.0 255.255.255.0 eq www log default (hitcnt=0) 0xdc46eb6e
access-list test_access line 2 extended deny icmp 198.51.100.0 255.255.255.0 198.51.110.0 255.255.255.0 alternate-address log errors interval 300 (hitcnt=0) 0x68f0b1cd
access-list test_R1_traffic; 1 elements; name hash: 0x2c20a0c
access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet (hitcnt=0) 0x11821a52
部署 ACL 后,设备配置通过资源模块列出上次的列表,但这次使用“已覆盖 (overridden)”状态
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_access; 1 elements; name hash: 0x96b5d78b
access-list test_access line 1 extended deny tcp 192.0.3.0 255.255.255.0 192.0.4.0 255.255.255.0 eq www log default (hitcnt=0) 0x7ab83be2
access-list test_global_access; 1 elements; name hash: 0xaa83124c
access-list test_global_access line 1 extended deny tcp 192.0.4.0 255.255.255.0 eq telnet 192.0.5.0 255.255.255.0 eq www (hitcnt=0) 0x243cead5
请注意,这次列表短得多 - ACL test_R1_traffic 已被删除,因为它未在部署的 ACL 定义中明确提及。这展示了“已替换 (replaced)”和“已覆盖 (overridden)”状态之间的区别。
您可以在 state: overridden 参考 gist 中查看所有命令和示例输出的完整详细列表。
状态已删除 (Deleted):删除不需要的
另一个更明显的用例是在设备上删除现有的 ACL,这在“已删除 (deleted)”状态中实现。在这种情况下,输入是要删除的 ACL 名称,相应的删除操作将通过删除在相应 ACL 下配置的所有 ACE 来删除特定 ACL 的条目。
例如,让我们使用在其他示例中已使用的棕色字段配置。要删除 ACL test_access,我们在输入变量中命名它。
- acls:
- name: test_access
剧本看起来与其他示例中的剧本完全一样,只是参数和值状态为:已删除。执行后,设备的配置为
ciscoasa# sh access-list
access-list cached ACL log flows: total 0, denied 0 (deny-flow-max 4096)
alert-interval 300
access-list test_R1_traffic; 1 elements; name hash: 0x2c20a0c
access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet (hitcnt=0) 0x11821a52
输出明显比之前的配置短,因为缺少整个 ACL。
您可以在state: deleted 参考 gist中查看此示例的所有命令和输出的完整详细列表。
状态渲染和状态解析:用于开发和离线工作
目前还有另外两种状态可用:“rendered” 和“parsed”。两者都比较特殊,因为它们不适用于生产环境,而是在开发您的剧本和设备配置期间使用。它们不会更改设备配置 - 而是以不同的格式输出将要更改的内容。
状态“rendered” 返回将执行以应用提供的配置的命令列表。根据上面使用的配置与我们的棕色字段设备配置给出的返回值内容
"rendered": [
"access-list test_access line 1 extended deny tcp 192.0.2.0 255.255.255.0 192.0.3.0 255.255.255.0 eq www log default",
"access-list test_access line 2 extended deny icmp 198.51.100.0 255.255.255.0 198.51.110.0 255.255.255.0 alternate-address log errors",
"access-list test_R1_traffic line 1 extended deny tcp 2001:db8:0:3::/64 eq www 2001:fc8:0:4::/64 eq telnet"
]
您可以在state: rendered 参考 gist中查看此示例的所有命令和输出的完整详细列表。
状态“parsed” 的作用类似,但它不返回将执行的命令,而是将配置作为 JSON 结构返回,该结构可以在后续的自动化任务或其他程序中重复使用。请参阅我们在state: parsed 参考 gist中解析示例的所有命令和输出的完整详细列表。
用例:对象组
如前所述,Ansible 内容集合支持第二个资源:对象组。可以将其视为网络、用户、安全组、协议、服务等。资源模块可用于定义它们或更改其定义。与 ACL 资源模块非常相似,基本工作流程通过变量结构定义它们,然后以状态参数标识的方式部署它们。状态基本上与 ACL 资源模块理解的状态相同。
由于这种相似性,我们这里将不再详细介绍,而是参考上面提到的不同状态示例。
但是,从安全角度来看,对象组资源模块至关重要:在现代 IT 环境中,通信关系不仅由 IP 地址定义,还可以由关注的对象类型定义:对于安全从业人员来说,能够在对象组中抽象这些类型并在以后的 ACL 中解决它们的通信关系至关重要。
这也解释了为什么我们选择这两个资源模块作为起点:它们紧密配合,共同为使用 Cisco ASA 设备系列实现自动化的安全方法铺平了道路。