我们希望听到您的意见!帮助我们深入了解 Ansible 生态系统的现状。
参加 Ansible 项目调查 2024

深入探讨 Cisco ASA 资源模块

深入探讨 Cisco ASA 资源模块

最近,我们发布了我们对应用于 Ansible 安全自动化计划目标用例的资源模块的看法。该原则在网络自动化领域众所周知,我们遵循既定的路径。虽然上一篇博文介绍了一些基本示例,但我们想展示更详细的用例,以及如何使用资源模块解决这些用例。

这篇博文深入探讨了新的 Cisco ASA 内容集合,该集合已在上一篇文章中介绍。我们将逐步介绍几个示例,并描述用例以及我们如何设想在现实世界场景中使用该集合。

Cisco ASA 认证内容集合:它是什么?

Cisco ASA 内容集合提供了自动化 Cisco 自适应安全设备系列 的方法 - 简称 Cisco ASA,因此得名。它们以防火墙和网络安全为重点,在市场上广为人知。

该集合的目的是将 Cisco ASA 设备集成到自动化的安全工作流程中。为此,该集合提供了模块来自动化设备的通用命令和配置交互,以及访问控制列表 (ACL) 和对象组 (OG) 的资源导向自动化。

如何安装 Cisco ASA 认证的 Ansible 内容集合

Cisco ASA 集合可供 Red Hat Ansible 自动化平台客户使用 自动化中心,这是我们提供的软件即服务,位于 cloud.redhat.com,也是 Red Hat 订阅者快速查找和使用 Red Hat 及其技术合作伙伴支持的内容的地方。

完成此操作后,即可轻松安装该集合

ansible-galaxy collection install cisco.asa

或者,您也可以 在 Ansible Galaxy 中查找该集合,这是我们用于在社区中共享内容的开源中心。

Cisco ASA 内容集合包含什么?

该集合的重点是提到的模块(以及支持它们的插件):有三个用于基本交互的模块,asa_facts、asa_cli 和 asa_config。如果您熟悉 Ansible 的其他网络和防火墙集合和模块,您会认出这种模式:这三个模块提供了与网络和防火墙解决方案交互的最简单方法。使用它们,可以接收一般数据,发送任意命令以及管理配置部分。

虽然这些模块已经为设备完全未自动化的环境提供了很大的价值,但本文的重点是该集合中的其他模块:资源模块 asa_ogs 和 asa_acls。作为资源模块,它们的作用范围有限,但使用该集合的用户可以专注于特定资源,而不会受到其他内容或配置项目的干扰。它们还简化了跨产品自动化,因为其他集合遵循相同的模式。

如果您仔细观察,您会发现另外两个模块:asa_ogs 和 asa_acls。正如我们在关于安全自动化资源模块的第一篇博文中提到的那样,这些是已弃用的模块,以前用于配置 ACL 和 OG。它们已被资源模块取代。

以集合方式连接到 Cisco ASA

该集合支持 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

完成所有这些设置后,我们现在可以深入研究实际的集合及其使用方法。在第一个用例中,我们想了解如何在 ASA 中管理 ACL。在我们深入研究 Ansible Playbook 示例之前,让我们快速讨论一下 ASA ACL 是什么以及自动化从业人员需要注意什么。

ASA 访问列表是在全局创建的,然后使用“access-group”命令应用。它们可以应用于入站或出站。在使用 Cisco ASA 防火墙上的访问列表时,用户需要注意以下几点

  • 当用户为从高安全级别到低安全级别的流量(即出站流量)创建 ACL 时,源 IP 地址是主机或网络的地址(而不是 NAT 转换后的地址)。

  • 当用户为从低安全级别到高安全级别的流量(即入站流量)创建 ACL 时,目标 IP 地址必须是以下两个中的一个

    • 8.3 之前的任何 ASA 版本的转换地址。
    • ASA 8.3 及更高版本的地址。
  • 访问列表始终在 NAT 转换之前进行检查。

此外,更改 ACL 很快就会变得非常复杂。这不仅仅是关于配置本身,还关于自动化从业人员的意图:应该将新的 ACL 添加到现有配置中吗?还是应该替换它?合并它们呢?

这些问题的答案通常取决于部署更改的环境和情况。更改 ACL 的不同方式在本文档和 Cisco ASA 内容集合中被记为“状态”:不同方式部署对 ACL 的更改。

ACL 模块知道以下状态

  • 已收集
  • 已合并
  • 已覆盖
  • 已替换
  • 已删除
  • 已渲染
  • 已解析

在本用例讨论中,我们将介绍所有这些状态,尽管并非总是详细介绍。但是,我们将为感兴趣的读者提供完整代码列表的链接。

请注意,虽然我们通常使用网络地址作为源和目标示例,但也可以使用其他值,如网络对象组。

状态已收集:使用配置数据填充清单

鉴于资源模块允许读取现有网络配置并将这些配置转换为结构化的数据模型,“已收集”状态相当于为该特定资源收集 Ansible Fact。如果特定配置片段应该在稍后作为变量重用,这将很有帮助。另一个用例是读取现有网络配置并将其存储为平面文件。该平面文件可以定期提交到 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"

状态“已收集”仅收集现有数据。与大多数其他状态相反,它不会更改任何配置。从读取 Brownfield 配置生成的最终数据结构如下所示

$ 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 中找到所有命令和输出的完整详细信息。

状态已合并:添加/更新配置

在第一个非更改状态之后,我们现在来看一个更改目标配置的状态:“已合并”。此状态也是所有可用资源模块的默认状态 - 因为它只是添加或更新用户提供的配置。简单明了。

例如,让我们来看以下现有设备配置

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 中的最后一个 ACE 配置,最好配置行号。

  • 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 中找到所有命令和输出的完整详细信息。

状态已替换:旧的出去,新的进来

另一个典型的情况是,当设备已经配置了包含现有 ACE 的 ACL 时,自动化从业人员希望用一组新的 ACE 更新 ACL,同时完全丢弃所有已配置的 ACE。

在这种情况下,状态“replaced”是理想的选择:顾名思义,replaced 状态将用用户提供的新的 ACE 集替换 ACL 中现有的 ACE。如果用户试图配置任何尚未在设备上预先配置的新的 ACL,它将充当合并状态,asa_acls 模块将尝试在 replace 运行中配置用户提供的 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 和目标 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 }}"

运行剧本后,网络设备配置按预期发生了更改:旧配置已替换为新配置。在没有相应配置需要替换的情况下,添加了新的配置

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 中查看此示例的所有命令和输出的完整详细列表。

状态覆盖:删除不需要的

如上一个示例中所述,ACL 定义中未明确提及的 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 后设备配置,通过资源模块列出上次时间,但这次使用 state“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 中查看此示例的所有命令和输出的完整详细列表。

状态删除:删除不需要的

另一个更明显的用例是删除设备上现有的 ACL,这在“deleted”状态中实现。在这种情况下,输入是要删除的 ACL 名称,相应的删除操作将通过删除在相应 ACL 下配置的所有 ACE 来删除特定 ACL 的条目。

例如,让我们使用其他示例中已经使用的棕色字段配置。要删除 ACL test_access,我们在输入变量中命名它

- acls:
   - name: test_access

剧本与其他示例中的剧本类似,只是参数和值 state: deleted 不同。执行它后,设备的配置为

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 设备系列的自动化安全方法铺平道路。