首页 > 其他分享 >Ansible2-安全自动化指南-全-

Ansible2-安全自动化指南-全-

时间:2024-05-20 13:12:31浏览次数:17  
标签:指南 name Ansible2 使用 ansible Ansible playbook 自动化 我们

Ansible2 安全自动化指南(全)

原文:zh.annas-archive.org/md5/CFD4FC07D470F8B8541AAD40C25E807E

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

IT 正在经历一次巨大的范式转变。从以正常运行时间作为 IT 成功的衡量标准的时代,我们正在转向不可变基础设施的理念,根据需求,我们可以自动地随时启动和销毁服务器。Ansible 在这种转变中扮演着主导角色。它已经成为各大公司和小公司选择的工具,用于单个服务器到整个集群的任务。

本书介绍了安全自动化。我们运用对 Ansible 的知识到不同的场景和工作负载中,这些场景和工作负载围绕着安全展开,因此得名。当无聊和单调的任务被自动化时,做这些任务的人可以集中精力解决他们所面对的安全问题。这为我们学习安全(培训)的方式、我们可以存储、处理和分析日志数据的数量(DFIR)、我们如何可以在没有任何中断的情况下保持应用安全更新(安全运营),以及更多内容提供了全新的观点。

在本书中,我们将分享使用 Ansible 可以实现的各种自动化类型的经验。你可能对其中一些内容很熟悉,或者对你来说它们可能是全新的。无论如何,我们希望你不要试图规定应该如何使用 Ansible,而是希望你阅读并理解如何使用每个 playbook/工作流程,使你的安全工作更快、更好、更可靠,或者只是为自己或他人创建复杂的基础架构场景而感到开心。

如果没有 Red Hat Ansible 的同事以及其他无数的博客和项目提供的优秀文档,本书将不可能问世,他们已经创建了安全、具有弹性的 playbooks,我们都可以从中学习并使用。

本书分为三个主要部分:

  • 构建有用的 playbook 所需的基本 Ansible

  • 安全自动化技术和方法

  • 扩展和编程 Ansible 以获得更多的安全性

我们的目标是让你快速更新你对 Ansible 的知识,然后让你变得对它更加高效,最后,你将看到如何通过扩展 Ansible 或创建你自己的安全模块来做更多事情

这本书涵盖的内容

第一章,介绍 Ansible Playbooks 和 Roles,介绍了您在 Ansible 中可能已经熟悉的术语。它们通过示例 playbooks 和运行这些 playbooks 所需的 Ansible 命令进行了解释。如果你觉得你的 Ansible 概念和技能有点生疏,可以从这里开始。

第二章,Ansible Tower、Jenkins 和其他自动化工具,全都是关于自动化的自动化。我们涵盖了与 Ansible 一起常用的调度自动化工具的使用,例如 Ansible Tower、Jenkins 和 Rundeck。如果您开始使用这些工具,那么记住何时安排和执行 playbooks 以及获取有关输出的通知等单调乏味的任务可以委托给这些工具,而不是留在您的头脑中。如果您还没有使用过这些工具,您应该阅读本章。

第三章,使用加密自动备份设置加固的 WordPress,涵盖了各种安全自动化技术和方法的探索。与任何技术或方法一样,我们所说的一些内容可能并不适用于您的用例。然而,通过采取一种主观的方法,我们向您展示了一种我们认为在很大程度上运行良好的方法。WordPress 是目前最流行的网站创建软件。通过使用 playbooks(并在 IT 自动化工具中运行),我们开始讨论一个 IT/ops 需求,即保持正在运行的服务器安全,并确保我们可以从故障中恢复。如果您负责管理网站(即使只是您自己的网站),这一章应该是有用的。如果您不使用 WordPress,在本章中有足够的内容让您思考如何将本章应用于您的用例。

第四章,日志监视和无服务器自动防御(AWS 中的 Elastic Stack),涵盖了日志监视和安全自动化,就像花生酱和果冻一样。在本章中,我们使用 Ansible 在 AWS 中的服务器上设置日志监视服务器基础架构。基于攻击通知,我们使用 AWS Lambda、Dynamo DB 和 AWS Cloudwatch 等 AWS 服务创建一个几乎实时的动态防火墙服务。

第五章,使用 OWASP ZAP 自动化 Web 应用程序安全测试,涵盖了测试网站安全性的最常见安全工作流程之一,即使用最流行的开源工具之一 OWASP ZAP。一旦我们弄清了基本工作流程,我们就会通过 Ansible 和 Jenkins 对您的网站进行持续扫描,使其超级强大。阅读本章,了解如何使用 Ansible 在处理持续安全扫描时与 Docker 容器一起工作。这是一个确保双赢的策略!

第六章,使用 Nessus 进行漏洞扫描,解释了使用 Nessus 与 Ansible 进行漏洞扫描的方法。本章涵盖了进行基本网络扫描、进行安全补丁审核和枚举漏洞的方法。

第七章,应用程序和网络的安全加固,展示了 Ansible 已经使我们能够以声明方式表达我们的安全思想。通过利用系统状态应该是什么的想法,我们可以基于标准(如 CIS 和 NIST)以及美国国防部的 STIGs 提供的指南创建安全加固剧本。熟悉使用现有安全文档来加固应用程序和服务器的方法,但最重要的是,以可重复自描述的方式进行,这是在版本控制下进行的。如果你和我们一样,多年来一直手动执行所有这些任务,你会很感激这对安全自动化的改变。

第八章,Docker 容器的持续安全扫描,介绍了如何对 Docker 容器运行安全扫描工具。许多现代应用程序都使用容器部署,本章将帮助你快速了解是否有容器存在漏洞,并且一如既往地,与 Ansible Tower 结合使用,如何使这成为一个持续的过程。

第九章,自动设置实验室进行取证收集、恶意软件分析,特别适用于恶意软件研究人员。如果你一直想使用 Cuckoo 沙箱和 MISP,但因为设置这些工具涉及的步骤太复杂而望而却步,那么本章将为你提供帮助。

第十章,编写用于安全测试的 Ansible 模块,介绍了我们如何扩展 Ansible 提供的功能,并学习其他项目如何使用 Ansible 提供优秀的软件解决方案。本章和下一章,带领我们进入本书的第三部分。

有时候,尽管 Ansible 自带了许多惊人的模块,但它们仍然不足以满足我们的需求。本章探讨了创建 Ansible 模块,如果我们可以这么说的话,它并不试图对方法非常正式。记住我们想要关注的是安全自动化,我们创建了一个模块来运行使用 ZAP 代理进行网站安全扫描。提供了完整的模块,这将帮助你在很短的时间内编写和使用你自己的模块。

第十一章,Ansible 安全最佳实践、参考和进一步阅读,介绍了如何使用 Ansible Vault 管理密码和凭证。它将帮助你建立自己的 Ansible Galaxy 实例。我们还介绍了其他使用 Ansible 剧本进行安全解决方案的项目,如 DebOps 和 Algo。我们还介绍了 AWX,这是 Ansible Tower 的免费开源版本,并向你展示如何设置和使用它。最后,我们简要讨论了预计在 2018 年第一或第二季度发布的 Ansible 2.5 版本。

为了阅读本书,你需要什么

Ansible 是一种用 Python2 编写的工具。对于控制机器,如果 Python2 安装了最低版本 2.6,那就没问题了。自 Ansible 2.2 起,Python3 作为技术预览版本得到支持。

这本书适合谁

这本书最理想的读者是那些明白自动化是实现可重复、无错误部署和基础架构、应用程序和网络配置的关键的人。不过,我们确实想要指明这一点。

如果您是负责网站、服务器和网络安全的系统管理员,那么这本书适合您。

安全顾问和分析师将通过专注于 第三章设置具有加密自动备份的强化 WordPress,到 第十章编写用于安全测试的 Ansible 模块 而受益。即使某些工作负载不适用于您,您也将了解如何使用 Ansible 为团队提供安全服务的见解。所有 DevOps 团队都愿意与将自动化视为与安全本身一样重要的人一起工作。

希望轻松部署安全服务器的应用程序开发人员尤其应该查看 第三章设置具有加密自动备份的强化 WordPress,到 第七章应用程序和网络的安全强化

如果您是以下人员之一,您将从这本书中受益最多:

  • 之前使用过 Ansible 基本命令的人

  • 对 Linux 和 Windows 操作系统熟悉的人。

  • 对 IP 地址、网络和软件安装程序有基本了解的人。

惯例

在本书中,您将找到一些区分不同类型信息的文本样式。以下是这些样式的一些示例及其含义的解释。文本中的代码单词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄显示如下:“harden.yml 执行 MySQL 服务器配置的加固” 代码块设置如下:

- name: deletes anonymous mysql user
  mysql_user:
    user: ""
    state: absent
    login_password: "{{ mysql_root_password }}"
    login_user: root

当我们希望引起您对代码块的特定部分的注意时,相关行或项目会以粗体显示:

- name: deletes anonymous mysql user
  mysql_user:
    user: ""
    state: absent
    login_password: "{{ mysql_root_password }}"
    login_user: root

任何命令行输入或输出写成如下格式:

ansible-playbook -i inventory playbook.yml

新术语重要单词 以粗体显示。您在屏幕上看到的单词,例如菜单或对话框中的单词,会以这种方式出现在文本中:“点击 确认安全异常 并继续执行安装步骤”。

警告或重要提示会以这种方式出现。

提示和技巧会以这种方式出现。

读者反馈

我们的读者的反馈意见始终受到欢迎。告诉我们您对这本书的看法 - 您喜欢或不喜欢什么。读者的反馈对我们很重要,因为它帮助我们开发您真正能充分利用的标题。要向我们发送一般反馈,只需发送电子邮件至[email protected],并在您的消息主题中提到书名。如果您在某个专题上有专业知识,并且您有兴趣撰写或贡献一本书,请参阅我们的作者指南,网址为www.packtpub.com/authors

客户支持

现在,您是 Packt 书籍的自豪所有者,我们有很多东西可以帮助您充分利用您的购买。

下载示例代码

你可以从www.packtpub.com的帐户中下载本书的示例代码文件。如果你在其他地方购买了这本书,你可以访问www.packtpub.com/support,并注册以直接将文件通过电子邮件发送给你。按照以下步骤下载代码文件:

  1. 使用您的电子邮件地址和密码登录或注册到我们的网站。

  2. 将鼠标指针悬停在顶部的 SUPPORT 选项卡上。

  3. 单击“代码下载与勘误”。

  4. 在搜索框中输入书名。

  5. 选择您要下载代码文件的书籍。

  6. 从下拉菜单中选择购买本书的位置。

  7. 单击“代码下载”。

下载文件后,请确保使用以下最新版本的解压缩或提取文件夹:

  • Windows 上的 WinRAR / 7-Zip

  • Mac 上的 Zipeg / iZip / UnRarX

  • Linux 上的 7-Zip / PeaZip

本书的代码捆绑包也托管在 GitHub 上,地址为github.com/PacktPublishing/Security-Automation-with-Ansible-2。我们还提供了来自我们丰富书籍和视频目录的其他代码捆绑包,地址为github.com/PacktPublishing/。来看看吧!

下载本书的彩色图像

我们还为您提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图像。彩色图像将帮助您更好地理解输出的变化。您可以从www.packtpub.com/sites/default/files/downloads/SecurityAutomationwithAnsible2_ColorImages.pdf下载此文件。

勘误

尽管我们已经尽一切努力确保内容的准确性,但错误还是会发生。如果您在我们的书籍中发现错误——也许是文字或代码上的错误——我们将不胜感激地请您向我们报告。通过这样做,您可以避免其他读者的困扰,并帮助我们改进本书的后续版本。如果您发现任何勘误,请访问www.packtpub.com/submit-errata,选择您的书籍,点击"勘误提交表格"链接,并输入您的勘误详情。一旦您的勘误被验证,您的提交将被接受,并且勘误将被上传到我们的网站或添加到该书籍的"勘误"部分的任何现有勘误列表中。要查看之前提交的勘误,请转至www.packtpub.com/books/content/support,并在搜索框中输入书名。所需信息将显示在"勘误"部分下面。

盗版

互联网上的版权物资盗版是跨所有媒体持续存在的问题。在 Packt,我们非常重视保护我们的版权和许可。如果您在互联网上的任何形式上发现我们作品的任何非法副本,请立即向我们提供位置地址或网站名称,以便我们采取补救措施。请通过[email protected]与我们联系,并附上可疑盗版材料的链接。感谢您帮助我们保护我们的作者和我们为您带来有价值内容的能力。

问题

如果您对本书的任何方面有问题,请通过[email protected]与我们联系,我们将尽力解决问题。

Ansible Playbooks 和 Roles 介绍

根据维基百科,Ansible 是一个自动化软件配置、配置管理和应用部署的开源自动化引擎。但你已经知道这一点了。这本书是关于将 IT 自动化软件的理念应用于信息安全自动化领域。

本书将带领你踏上 安全自动化 之旅,展示 Ansible 在现实世界中的应用。

在这本书中,我们将以一种结构化、模块化的方式,使用一种简单易读的格式 YAML 自动化执行与安全相关的任务。最重要的是,你将学会创建的内容是可重复的。这意味着一旦完成,你可以专注于微调、扩展范围等。这个工具确保我们可以构建和销毁从简单应用堆栈到简单但广泛的多应用框架一切。

如果你已经玩过 Ansible,我们假设你已经这样做了,那么你肯定遇到了以下一些术语:

  • Playbook

  • Ansible 模块

  • YAML

  • Roles

  • 模板(Jinja2)

别担心,我们将在本章节中解释所有上述术语。一旦你对这些主题感到舒适,我们将继续覆盖调度器工具,然后转向构建安全自动化 playbooks。

需记住的 Ansible 术语

像所有新的主题或话题一样,熟悉该主题或话题的术语是一个不错的主意。我们将介绍一些我们将在整本书中使用的 Ansible 术语,如果在任何时候你无法跟上,你可能需要回到这一章节,重新理解特定术语。

Playbooks

在经典意义上,playbook 是关于足球比赛中的进攻和防守战术的。球员们会记录这些战术(行动计划),通常以图表形式呈现在一本书中。

在 Ansible 中,playbook 是一个 IT 过程的一系列有序步骤或指令。把它想象成一本可以被人类和计算机同时阅读和理解的精心撰写的说明书。

在随后的章节中,我们将专注于安全方面的自动化,引导我们构建简单和复杂的 playbooks。

一个 Ansible playbook 命令看起来像这样:

ansible-playbook -i inventory playbook.yml

暂时忽略-i 标志,并注意 playbook 文件的扩展名。

正如 docs.ansible.com/ansible/playbooks_intro.html 中所述:

"Playbooks 以 YAML 格式表达(参见 YAML 语法 (docs.ansible.com/ansible/YAMLSyntax.html), 且具有最少的语法,其旨在有意尝试不成为编程语言或脚本,而是一个配置或过程的模型。"

Ansible 模块

Ansible 随附了一些模块(称为 模块库),可以直接在远程主机上执行或通过 playbook 执行。Playbook 中的任务调用模块来完成工作。

Ansible 有许多模块,其中大多数是由社区贡献和维护的。核心模块由 Ansible 核心工程团队维护,并将随着 Ansible 一起发布。

用户还可以编写自己的模块。这些模块可以控制系统资源,如服务、软件包或文件(实际上是任何东西),或者处理执行系统命令。

下面是 Ansible 提供的模块列表:docs.ansible.com/ansible/latest/modules_by_category.html#module-index

如果您使用 Dash (kapeli.com/dash) 或 Zeal (zealdocs.org/),您可以下载离线版本以便参考。

模块也可以通过命令行执行。我们将使用模块来编写 playbook 中的所有任务。所有模块在技术上都返回 JSON 格式的数据。

模块应该是幂等的,如果检测到当前状态与期望的最终状态匹配,则应该避免进行任何更改。当使用 Ansible playbook 时,这些模块可以触发 change events,以通知 handlers 运行额外的任务。

每个模块的文档可以通过命令行工具 ansible-doc 访问:

$ ansible-doc apt

我们可以列出主机上所有可用的模块:

$ ansible-doc -l

通过执行 httpd 模块,在所有节点分组为 webservers 下启动 Apache Web 服务器。注意使用了 -m 标志:

$ ansible webservers -m service -a "name=httpd state=started"

这个片段展示了完全相同的命令,但是在一个 YAML 语法的 playbook 中:

- name: restart webserver
  service:
    name: httpd
    state: started

每个模块包含多个参数和选项,通过查看它们的文档和示例来了解模块的特性。

用于编写 Ansible playbook 的 YAML 语法

Ansible playbook 使用 YAML 编写,它代表 YAML Ain't Markup Language

根据官方文档 (yaml.org/spec/current.html):

"YAML Ain't Markup Language"(缩写为 YAML)是一种设计成对人类友好并且与现代编程语言一起使用的数据序列化语言,用于日常任务。

Ansible 使用 YAML 是因为它比其他常见的数据格式(如 XML 或 JSON)更易于人类阅读和编写。所有的 YAML 文件(无论它们是否与 Ansible 相关)都可以选择以 --- 开始并以 ... 结束。这是 YAML 格式的一部分,表示文档的开始和结束。

YAML 文件应该以 .yaml.yml 结尾。YAML 区分大小写。

您还可以使用诸如 www.yamllint.com 这样的 Linters,或者您的文本编辑器插件来进行 YAML 语法的代码检查,这有助于您排除任何语法错误等等。

这里是一个简单 playbook 的示例,展示了来自 Ansible 文档的 YAML 语法(docs.ansible.com/ansible/playbooks_intro.html#playbook-language-example):

- hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  remote_user: root

  tasks:
  - name: Ensure apache is at the latest version
    yum:
      name: httpd
      state: latest
  - name: Write the apache config file
    template:
      src: /srv/httpd.j2
      dest: /etc/httpd.conf

    notify:
    - restart apache

  - name: Ensure apache is running (and enable it at boot)
    service:
      name: httpd
      state: started
      enabled: yes

  handlers:
    - name: Restart apache
      service:
        name: httpd
        state: restarted

Ansible 角色

虽然 playbook 提供了一种以预定义顺序执行 plays 的好方法,但 Ansible 上有一个很棒的功能将整个理念提升到完全不同的层次。角色是一种方便的方式来捆绑任务,支持文件和模板等支持资产,并带有一组自动搜索路径。

通过使用大多数程序员熟悉的 包含 文件和文件夹的概念,并指定被包含的内容,playbook 变得无限可读且易于理解。角色基本上由任务、处理程序和配置组成,但通过向 playbook 结构添加附加层,我们可以轻松获得大局观以及细节。

这样可以实现可重用的代码,并且在负责编写 playbook 的团队中分工明确。例如,数据库专家编写了一个角色(几乎像是一个部分 playbook)来设置数据库,安全专家则编写了一个加固此类数据库的角色。

虽然可以在一个非常大的文件中编写 playbook,但最终你会想要重用文件并开始组织事务。

大而复杂的 playbook 难以维护,很难重用大 playbook 的部分。将 playbook 拆分为角色允许非常高效的代码重用,并使 playbook 更容易理解。

在构建大 playbook 时使用角色的好处包括:

  • 协作编写 playbooks

  • 重用现有角色

  • 角色可以独立更新、改进

  • 处理变量、模板和文件更容易

LAMP 通常代表 Linux,Apache,MySQL,PHP。这是一种流行的软件组合,用于构建 Web 应用程序。如今,在 PHP 世界中另一个常见的组合是 LEMP,即 Linux,NGINX,MySQL,PHP

这是一个可能的 LAMP 堆栈 site.yml 的示例:

- name: LAMP stack setup on ubuntu 16.04
  hosts: all
  gather_facts: False
  remote_user: "{{remote_username}}"
  become: yes

 roles:
   - common
   - web
   - db
   - php

注意角色列表。仅通过阅读角色名称,我们就可以了解该角色下可能包含的任务类型。

使用 Jinja2 的模板

Ansible 使用 Jinja2 模板来实现动态表达式和访问变量。在 playbook 和任务中使用 Jinja2 变量和表达式使我们能够创建非常灵活的角色。通过向这种方式编写的角色传递变量,我们可以使相同的角色执行不同的任务或配置。使用模板语言,比如 Jinja2,我们能够编写简洁且易于阅读的 playbooks。

通过确保所有模板化发生在 Ansible 控制器上,Jinja2 不需要在目标机器上。只复制所需的数据,这减少了需要传输的数据量。正如我们所知,数据传输量越少,通常执行速度越快,反馈越快。

Jinja 模板示例

一个良好模板语言的标志是允许控制内容而不显得是完整的编程语言。Jinja2 在这方面表现出色,通过提供条件输出的能力,如使用循环进行迭代等等。

让我们看一些基本示例(显然是 Ansible playbook 相关的),看看是什么样子。

条件示例

仅当操作系统家族为 Debian 时执行:

tasks:
  - name: "shut down Debian flavored systems"
    command: /sbin/shutdown -t now
    when: ansible_os_family == "Debian"

循环示例

下面的任务使用 Jinja2 模板添加用户。这允许 playbooks 中的动态功能。我们可以使用变量在需要时存储数据,只需更新变量而不是整个 playbook:

- name: add several users
  user:
    name: "{{ item.name }}"
    state: present
    groups: "{{ item.groups }}"
  with_items:
    - { name: 'testuser1', groups: 'wheel' }
    - { name: 'testuser2', groups: 'root' }

LAMP 栈 playbook 示例 - 结合所有概念

我们将看看如何使用我们迄今学到的技能编写一个 LAMP 栈 playbook。这是整个 playbook 的高层次结构:

inventory               # inventory file
group_vars/             #
   all.yml              # variables
site.yml                # master playbook (contains list of roles)
roles/                  #
    common/             # common role
        tasks/          #
            main.yml    # installing basic tasks
    web/                # apache2 role
        tasks/          #
            main.yml    # install apache
        templates/      #
            web.conf.j2 # apache2 custom configuration
        vars/           # 
            main.yml    # variables for web role 
        handlers/       #
            main.yml    # start apache2
    php/                # php role
        tasks/          # 
            main.yml    # installing php and restart apache2
    db/                 # db role
        tasks/          #
            main.yml    # install mysql and include harden.yml
            harden.yml  # security hardening for mysql
        handlers/       #
            main.yml    # start db and restart apache2
        vars/           #
            main.yml    # variables for db role

让我们从创建一个清单文件开始。下面的清单文件是使用静态手动输入创建的。这是一个非常基本的静态清单文件,我们将在其中定义一个主机,并设置用于连接到它的 IP 地址。

根据需要配置以下清单文件:

[lamp]
lampstack    ansible_host=192.168.56.10

下面的文件是 group_vars/lamp.yml,其中包含所有全局变量的配置:

remote_username: "hodor"

下面的文件是 site.yml,这是启动的主要 playbook 文件:

- name: LAMP stack setup on Ubuntu 16.04
 hosts: lamp
 gather_facts: False
 remote_user: "{{ remote_username }}"
 become: True

 roles:
   - common
   - web
   - db
   - php

下面是 roles/common/tasks/main.yml 文件,它将安装 python2curlgit

# In ubuntu 16.04 by default there is no python2
- name: install python 2
  raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)

- name: install curl and git
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - curl
    - git

下面的任务,roles/web/tasks/main.yml,执行多个操作,如安装和配置 apache2。它还将服务添加到启动过程中:

- name: install apache2 server
  apt:
    name: apache2
    state: present

- name: update the apache2 server configuration
  template: 
    src: web.conf.j2
    dest: /etc/apache2/sites-available/000-default.conf
    owner: root
    group: root
    mode: 0644

- name: enable apache2 on startup
  systemd:
    name: apache2
    enabled: yes
  notify:
    - start apache2

notify 参数将触发 roles/web/handlers/main.yml 中找到的处理程序:

- name: start apache2
  systemd:
    state: started
    name: apache2

- name: stop apache2
  systemd:
    state: stopped
    name: apache2

- name: restart apache2
  systemd:
    state: restarted
    name: apache2
    daemon_reload: yes

模板文件将从 role/web/templates/web.conf.j2 中获取,该文件使用 Jinja 模板,还从本地变量中获取值:

<VirtualHost *:80><VirtualHost *:80>
    ServerAdmin {{server_admin_email}}
    DocumentRoot {{server_document_root}}

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

本地变量文件位于 roles/web/vars/main.yml

server_admin_email: [email protected]
server_document_root: /var/www/html

类似地,我们也会编写数据库角色。下面的文件 roles/db/tasks/main.yml 包括在提示时安装数据库服务器并分配密码。在文件末尾,我们包含了 harden.yml,它执行另一组任务:

- name: set mysql root password
  debconf:
    name: mysql-server
    question: mysql-server/root_password
    value: "{{ mysql_root_password | quote }}"
    vtype: password

- name: confirm mysql root password
  debconf: 
    name: mysql-server
    question: mysql-server/root_password_again
    value: "{{ mysql_root_password | quote }}"
    vtype: password

- name: install mysqlserver
  apt:
    name: "{{ item }}"
    state: present 
  with_items:
    - mysql-server
    - mysql-client

- include: harden.yml

harden.yml 执行 MySQL 服务器配置的加固:

- name: deletes anonymous mysql user
  mysql_user:
    user: ""
    state: absent
    login_password: "{{ mysql_root_password }}"
    login_user: root

- name: secures the mysql root user
  mysql_user: 
    user: root
    password: "{{ mysql_root_password }}"
    host: "{{ item }}"
    login_password: "{{mysql_root_password}}"
    login_user: root
 with_items:
   - 127.0.0.1
   - localhost
   - ::1
   - "{{ ansible_fqdn }}"

- name: removes the mysql test database
  mysql_db:
    db: test
    state: absent
    login_password: "{{ mysql_root_password }}"
    login_user: root

- name: enable mysql on startup
  systemd:
    name: mysql
    enabled: yes

  notify:
    - start mysql

db 服务器角色也有类似于 web 角色的 roles/db/handlers/main.yml 和本地变量:

- name: start mysql
  systemd:
    state: started
    name: mysql

- name: stop mysql
  systemd:
    state: stopped
    name: mysql

- name: restart mysql
  systemd:
    state: restarted
    name: mysql
    daemon_reload: yes

下面的文件是 roles/db/vars/main.yml,其中包含配置服务器时的 mysql_root_password。我们将在未来的章节中看到如何使用 ansible-vault 来保护这些明文密码:

mysql_root_password: R4nd0mP4$$w0rd

现在,我们将安装 PHP 并通过重新启动 roles/php/tasks/main.yml 服务来配置它与 apache2 一起工作:

- name: install php7
  apt:
    name: "{{ item }}"
    state: present
  with_items:
    - php7.0-mysql
    - php7.0-curl
    - php7.0-json
    - php7.0-cgi
    - php7.0
    - libapache2-mod-php7

- name: restart apache2
  systemd:
    state: restarted
    name: apache2
    daemon_reload: yes

要运行此剧本,我们需要在系统路径中安装 Ansible。请参阅docs.ansible.com/ansible/intro_installation.html获取安装说明。

然后针对 Ubuntu 16.04 服务器执行以下命令来设置 LAMP 堆栈。当提示系统访问用户 hodor 时,请提供密码:

$ ansible-playbook -i inventory site.yml

完成剧本执行后,我们将准备在 Ubuntu 16.04 机器上使用 LAMP 堆栈。您可能已经注意到,每个任务或角色都可以根据我们在剧本中的需要进行配置。角色赋予了将剧本泛化并使用变量和模板轻松定制的能力。

摘要

我们已经使用 Ansible 的各种功能对一个相当不错的真实世界堆栈进行了编码。通过思考 LAMP 堆栈概述中的内容,我们可以开始创建角色。一旦我们确定了这一点,就可以将单个任务映射到 Ansible 中的模块。任何需要复制预定义配置但具有动态生成输出的任务都可以使用我们模板中的变量和 Jinja2 提供的结构来完成。

我们将使用同样的方法来进行各种安全相关的设置,这些设置可能需要一些自动化用于编排、操作等。一旦我们掌握了在运行于我们笔记本电脑上的虚拟机上执行此操作的方法,它也可以被重新用于部署到您喜欢的云计算实例上。输出是人类可读的文本,因此可以添加到版本控制中,各种角色也可以被重复使用。

现在,我们已经对本书中将要使用的术语有了相当不错的了解,让我们准备好最后一块拼图。在下一章中,我们将学习和理解如何使用自动化和调度工具,例如 Ansible Tower、Jenkins 和 Rundeck,根据某些事件触发器或时间持续时间来管理和执行基于剧本的操作。

Ansible Tower、Jenkins 和其他自动化工具

Ansible 很强大。一旦你意识到写下配置和提供系统的方式的无数好处,你就再也不想回去了。事实上,你可能想要继续为复杂的云环境编写 playbooks,为数据科学家部署堆栈。经验法则是,如果你可以编写脚本,你就可以为其创建一个 playbook。

假设你已经这样做了。为各种场景构建不同的 playbooks。如果你看到了将基础架构的构建和配置编码化的优势,你显然会想要将你的 playbooks 放入版本控制下:

存储在版本控制下的多个 playbooks,准备部署到系统进行配置

到目前为止,我们已经解决了围绕自动化的有趣挑战:

  • 现在我们有了对多个目标执行 重放 命令的能力

  • 记住,如果 playbooks 是以幂等的方式,我们可以安全地对我们的目标运行它们 n 次而不必担心任何问题

  • 凭借它们是基于文本的文档,我们获得了版本控制和由此带来的所有好处

现在仍然需要手动的是,我们需要某人或某物来执行 ansible-playbook 命令。不仅如此,这个某人或某物还需要执行以下操作:

  • 记住何时执行 playbooks

  • 相应地安排它们的时间表

  • 安全存储秘密(通常我们需要 SSH 密钥才能登录)

  • 存储输出或记住重新运行 playbook 如果出现失败的情况

当我们想起记住细微之处时,我们都可以渴望成为那样的壮观人物,或者我们可以接受,这些注重细节、基于调度的任务最好由称职的软件而不是超人来完成!

超人将有能力记住、安排、执行并通知有关 playbooks 的情况

原来我们并不都需要成为超人。我们可以简单地使用安排和自动化工具,比如 Ansible Tower、Jenkins 或 Rundeck 来完成我们之前定义的所有任务,以及更多。

在本章中,我们将查看我们提到的所有三个工具,以了解它们提供了什么,以便将我们的自动化提升到自动化的下一个抽象层次。

具体来说,我们将涵盖以下主题:

  • 安装和配置 Ansible Tower

  • 使用 Ansible Tower 管理 playbooks 和调度

  • 安装和配置 Jenkins

  • 安装和配置 Rundeck

使用调度工具来启用下一层次的自动化

调度和自动化工具使我们能够自动化诸如持续集成和持续交付等任务。它们能够通过提供以下相当标准的服务来实现这一点:

  • 我们可以使用基于 web 的 UI 来配置它们

  • 通常,这是一个基于 REST 的 API,以便我们可以以编程方式使用它们的功能

  • 能够对其本地存储或可能是另一个服务(OAuth/安全断言标记语言 (SAML))进行身份验证

  • 它们从根本上为我们提供了一种清晰的方式来自动化任务以适应我们的工作流程

大多数与安全相关的自动化归结为一遍又一遍地执行类似的任务并查看差异。当您从事安全运营和安全评估时,这一点尤为真实。

请记住,通过使用 Ansible 角色和包含它们的 playbooks,我们已经在朝着进行安全自动化的目标迈出了一步。现在我们的目标是消除记得执行那些 playbooks 的麻烦工作并开始进行。

有三个主要竞争对手用于这种类型的自动化。它们在这里列出并描述:

  • Ansible Tower

  • Jenkins

  • Rundeck

工具 我们的看法 **许可证 **
Ansible Tower 由 Ansible 制造商推出的出色工具,非常适合 IT 自动化的理念,我们将其扩展到我们的安全需求。 付费,有免费试用版
Jenkins 工作流引擎,很多 CI/CD 流水线的主力。有数百个插件来扩展其核心功能。如果考虑价格或许可证问题,这是最佳选择。 免费和开源
Rundeck 用于作业调度和自动化的优秀工具。 有付费的专业版本

在本章中,我们将安装和配置所有三个工具,以便让您开始使用。

红帽公司于 2015 年 10 月收购了 Ansible,他们表示计划开源 Ansible Tower。他们在 2016 年 AnsibleFest 上宣布了这一消息。您可以在 www.ansible.com/open-tower 上关注该进展。

起步运行

让我们从设置我们提到的三个工具开始,看一下它们的一些特点。

设置 Ansible Tower

有多种方法可以安装 Ansible Tower 试用版。最简单的设置方式是使用它们现有的镜像从 www.ansible.com/tower-trial 获取。

您还可以使用他们的捆绑安装手动设置。在安装之前,请查看 docs.ansible.com/ansible-tower/3.1.4/html/installandreference/index.html 的要求。

运行以下命令在 Ubuntu 16.04 操作系统中安装 Ansible Tower:

$ sudo apt-get install software-properties-common

$ sudo apt-add-repository ppa:ansible/ansible

$ wget https://releases.ansible.com/ansible-tower/setup/ansible-tower-setup-latest.tar.gz

$ tar xvzf ansible-tower-setup-latest.tar.gz

$ cd ansible-tower-setup-<tower_version>

然后编辑清单文件以更新密码和其他变量,并运行设置。 清单文件包含了用于塔管理员登录帐户的admin_password,如果我们正在设置多节点设置,则需要 Postgres 数据库的pg_hostpg_port。最后是用于排队操作的rabbitmq详情。

[tower]
localhost ansible_connection=local

[database]

[all:vars]
admin_password='strongpassword'

pg_host='' # postgres.domain.com
pg_port='' #5432

pg_database='awx'
pg_username='awx'
pg_password='postgrespasswordforuserawx'

rabbitmq_port=5672
rabbitmq_vhost=tower
rabbitmq_username=tower
rabbitmq_password='giverabitmqpasswordhere'
rabbitmq_cookie=cookiemonster

# Needs to be true for fqdns and ip addresses
rabbitmq_use_long_name=false
$ sudo ./setup.sh

如果您已经安装了 Vagrant,则可以简单地下载他们的 Vagrant box 来开始使用。

在运行以下命令之前,请确保您的主机系统上已安装了 Vagrant:

$ vagrant init ansible/tower

$ vagrant up

$ vagrant ssh

它会提示您输入 IP 地址、用户名和密码以登录到 Ansible Tower 仪表板。

然后在浏览器中导航至 https://10.42.0.42 并接受 SSL 错误以继续。可以通过在 /etc/tower 配置中提供有效证书来修复此 SSL 错误,并需要重新启动 Ansible Tower 服务。输入登录凭据以访问 Ansible Tower 仪表板:

登录后,会提示您输入 Ansible Tower 许可证:

Ansible Tower 还提供了基于角色的身份验证控制RBAC),为不同的用户和组提供了细粒度的控制,以管理 Tower。下面的截图显示了使用系统管理员权限创建新用户的过程:

要将清单添加到 Ansible Tower 中,我们可以简单地手动输入它,还可以使用动态脚本从云提供商那里收集清单,方法是提供身份验证(或)访问密钥。下面的截图显示了我们如何将清单添加到 Ansible Tower 中,还可以通过在 YAML 或 JSON 格式中提供变量来为不同的主机提供变量:

我们还可以通过在凭据管理中提供它们来向 tower 添加凭据(或)密钥,这些凭据也可以重复使用。

Ansible Tower 中存储的秘密信息使用每个 Ansible Tower 集群独有的对称密钥进行加密。一旦存储在 Ansible Tower 数据库中,凭据只能在 Web 界面中使用,而不能查看。Ansible Tower 可以存储的凭据类型包括密码、SSH 密钥、Ansible Vault 密钥和云凭据。

一旦我们收集了清单,就可以创建作业来执行 Playbook 或即席命令操作:

在这里,我们选择了 shell 模块,并针对两个节点运行了 uname -a 命令:

一旦启动执行,我们就可以在仪表板中看到标准输出。我们也可以使用 REST API 访问:

请参考 Ansible Tower 文档获取更详细的参考资料。

还有另一种使用 Ansible Tower 的方式:tower-cli 是 Ansible Tower 的命令行工具。可以通过 pip install ansible-tower-cli 命令开始使用。

Ansible Tower REST API 是与系统交互的一种非常强大的方式。

这基本上允许您使用易于遵循的 Web GUI 设计 Playbook 工作流程等,同时还可以从另一个 CI/CD 工具(如 Jenkins)调用此功能。顺便说一句,Jenkins 是接下来要设置和学习的软件。

设置 Jenkins

让我们使用一个 Ansible playbook 来安装 Jenkins 并开始使用它。

以下代码片段是我们为在 Ubuntu 16.04 操作系统中设置 Jenkins 编写的 Ansible playbook 的片段。

完成设置后,Playbook 将返回首次登录到应用程序所需的默认管理员密码:

- name: installing jenkins in ubuntu 16.04
  hosts: "192.168.1.7"
  remote_user: ubuntu
  gather_facts: False
  become: True

tasks:
  - name: install python 2
    raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)

  - name: install curl and git
    apt: name={{ item }} state=present update_cache=yes

    with_items:
      - curl
      - git

  - name: adding jenkins gpg key
    apt_key:
      url: https://pkg.jenkins.io/debian/jenkins-ci.org.key
      state: present

  - name: jeknins repository to system
    apt_repository:
      repo: http://pkg.jenkins.io/debian-stable binary/
      state: present

  - name: installing jenkins
    apt:
      name: jenkins
      state: present
      update_cache: yes

  - name: adding jenkins to startup
    service:
      name: jenkins
      state: started
      enabled: yes

  - name: printing jenkins default administration password
    command: cat /var/lib/jenkins/secrets/initialAdminPassword
    register: jenkins_default_admin_password

  - debug:
      msg: "{{ jenkins_default_admin_password.stdout }}"

要设置 Jenkins,请运行以下命令。其中 192.168.1.7 是 Jenkins 将被安装在的服务器 IP 地址:

ansible-playbook -i '192.168.1.7,' site.yml --ask-sudo-pass

现在我们可以配置 Jenkins 来安装插件、运行定期作业以及执行许多其他操作。首先,我们必须通过浏览到 http://192.168.1.7:8080 并提供自动生成的密码来导航到 Jenkins 仪表板。如果 Playbook 在没有任何错误的情况下运行,则会在操作结束时显示密码:

通过填写详细信息并确认登录到 Jenkins 控制台来创建新用户:

现在我们可以在 Jenkins 中安装自定义插件,导航至“管理 Jenkins”选项卡,选择“管理插件”,然后导航至“可用”选项卡。在“过滤器:”中输入插件名称为 Ansible。然后选中复选框,单击“安装但不重新启动”:

现在我们准备好使用 Jenkins 的 Ansible 插件了。在主仪表板中创建一个新项目,为其命名,然后选择自由风格项目以继续:

现在我们可以配置构建选项,这是 Jenkins 将为我们提供更大灵活性以定义我们自己的触发器、构建说明和后构建脚本的地方:

上述截图是一个构建调用 Ansible 临时命令的示例。这可以根据某些事件修改为 ansible-playbook 或基于特定事件的任何其他脚本。

Jenkins Ansible 插件还提供了有用的功能,例如从 Jenkins 本身配置高级命令和传递凭据、密钥。

一旦基于事件触发了构建,它可以被发送到某个构件存储中,也可以在 Jenkins 构建控制台输出中找到:

这是执行动态操作的非常强大的方式,例如基于对存储库的代码推送触发自动服务器和堆栈设置,以及定期扫描和自动报告。

设置 Rundeck

以下 Ansible playbook 将在 Ubuntu 16.04 操作系统上设置 Rundeck。它还添加了启动进程的 Rundeck 服务:

- name: installing rundeck on ubuntu 16.04
  hosts: "192.168.1.7"
  remote_user: ubuntu
  gather_facts: False
  become: True

  tasks:
    - name: installing python2 minimal
      raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)

    - name: java and curl installation
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes

      with_items:
        - curl
        - openjdk-8-jdk

    - name: downloading and installing rundeck deb package
      apt:
        deb: "http://dl.bintray.com/rundeck/rundeck-deb/rundeck-2.8.4-1-GA.deb"

    - name: add to startup and start rundeck
      service:
        name: rundeckd
        state: started

要设置 Rundeck,请运行以下命令。其中 192.168.1.7 是 Rundeck 将安装在的服务器 IP 地址:

ansible-playbook -i '192.168.1.7,' site.yml --ask-sudo-pass

成功执行后,在浏览器中导航至 http://192.168.1.7:4440,您将看到 Rundeck 应用程序的登录面板。登录到 Rundeck 的默认用户名和密码是 admin

现在我们可以创建一个新项目开始工作。提供一个新的项目名称,并暂时使用默认设置:

图片

现在,我们可以将多个主机添加到 Rundeck 中执行多个操作。下面的屏幕截图显示了在多个节点上运行 uname -a 命令的示例,与 osArch: amd64 匹配,我们也可以为不同的用例创建过滤器:

图片

使用 Rundeck,我们还可以按照特定时间安排作业运行,并以不同的格式存储输出。Rundeck 还提供了可集成到现有工具集中的 REST API。

安全自动化用例。

现在,一旦我们设置好了工具,让我们来执行一些标准任务,以便让我们可以利用它们做一些有用的事情。如果你还没注意到,我们喜欢列表。以下是一些任务的列表,这些任务将使您能够为对您重要的事物构建自动化层:

  1. 添加 playbooks 或连接您的源代码管理(SCM)工具,如 GitHub/GitLab/BitBucket。

  2. 身份验证和数据安全。

  3. 记录输出和管理自动化作业的报告。

  4. 作业调度。

  5. 警报、通知和 Webhooks。

添加 playbooks。

刚开始时,我们可能希望将自定义 playbooks 添加到 IT 自动化工具中,或者可能将它们添加到 SCM 工具,如 GitHub、GitLab 和 BitBucket 中。我们将配置并将我们的 playbooks 添加到这里讨论的所有三个工具中。

Ansible Tower 配置。

Ansible Tower 有多个功能可添加 playbooks 进行调度和执行。我们将看看如何添加自定义编写的 playbooks(手动)以及从 Git 等版本控制系统添加 playbooks。还可以从 Ansible Galaxy 拉取 playbooks。Ansible Galaxy 是您查找、重用和共享最佳 Ansible 内容的中心。

要将 playbooks 添加到 Ansible Tower 中,我们必须首先创建项目,然后选择 SCM 类型为 Manual,并添加已经存在的 playbooks。

警告/var/lib/awx/projects 中没有可用的 playbook 目录。要么该目录为空,要么所有内容已分配给其他项目。在那里创建一个新目录,并确保 awx 系统用户可以读取 playbook 文件,或者让 Tower 使用前面讨论过的 SCM 类型选项直接从源代码控制中检索您的 playbooks。

我们可以选择 SCM 类型设置为 Git,并提供指向 playbook 的 github.com URL:

图片

Git SCM 添加 playbooks 到项目中。

我们还可以在 CONFIGURE TOWER 下更改 PROJECTS_ROOT 来更改此位置。

添加的 playbooks 是通过创建作业模板来执行的。然后我们可以安排这些作业(或者)可以直接启动:

以下是为 playbook 执行创建的新作业模板的屏幕截图:

图片

Playbook 执行作业模板。

作业运行成功并显示输出如下截图:

Ansible Tower 中的 Playbook 执行输出

Jenkins Ansible 集成配置

毫不奇怪,Jenkins 支持 SCM 以使用 Playbook 和本地目录用于手动 Playbook。这可以通过构建选项进行配置。Jenkins 支持即席命令和 Playbook 作为构建(或)后置构建操作触发。

以下屏幕截图显示了我们如何指定我们的存储库并指定分支。如果要访问私有存储库,我们还可以指定凭据:

添加基于 Github(SCM)的 Playbooks 以进行构建

然后,我们可以通过指定 Playbook 的位置并根据需要定义清单和变量来添加 Playbook 路径:

在构建触发器启动 Playbook 执行

最后,我们可以通过触发 Jenkins 构建来执行 Jenkins 作业(或者)我们可以将其与其他工具集成:

Playbook 执行的 Jenkins 构建输出

Rundeck 配置

Rundeck 支持添加自定义 Playbook,以及 SCM 和许多其他选项。以下屏幕截图显示了使用作业功能在 Rundeck 中添加 Playbook 和模块的不同选项。

Rundeck 有多个选项供我们选择

用于变量和密钥的 Rundeck Ansible Playbook 配置

包括作业详情概述的 Rundeck 作业定义

身份验证和数据安全

当我们谈论自动化和与系统一起工作时,我们应该谈论安全性。我们将继续谈论安全自动化,因为这是本书的标题。

工具提供的一些安全功能包括:

  • RBAC(身份验证和授权)

  • Web 应用程序通过 TLS/SSL(数据在传输中的安全性)

  • 用于存储密钥的加密(数据在静止时的安全性)

Ansible Tower 的 RBAC

Ansible Tower 支持 RBAC 以管理具有不同权限和角色的多个用户。企业版还支持 轻量目录访问协议 (LDAP) 集成以支持 Active Directory。此功能允许我们为访问 Ansible Tower 创建不同级别的用户。例如:

  • 运维团队需要系统管理员角色来执行 Playbook 执行和其他活动,如监视

  • 安全团队需要系统审计员角色来执行符合标准(如 支付卡行业数据安全标准 (PCI DSS) 或甚至内部策略验证)的审计检查

  • 普通用户,如团队成员,可能只想查看事物的进展,以状态更新和作业状态的成功或失败的形式

用户可以被分配到不同类型的角色

Ansible Tower 的 TLS/SSL

默认情况下,Ansible Tower 使用自签名证书在 /etc/tower/tower.cert/etc/tower/tower.key 上进行 HTTPS,这些可以在设置脚本中配置。以后我们也可以使用相同的文件名进行更新。

获取更多信息,请访问 docs.ansible.com/ansible-tower/latest/html/installandreference/install_notes_reqs.html#installation-notes

Ansible Tower 的加密和数据安全

Ansible Tower 已经创建了内置安全性,用于处理包括密码和密钥在内的凭据的加密。它使用 Ansible Vault 执行此操作。它将数据库中的密码和密钥信息进行加密。

阅读更多请访问 docs.ansible.com/ansible-tower/latest/html/userguide/credentials.html

Jenkins 的 RBAC

在 Jenkins 中,这是一个更通用的工具,我们可以通过使用插件来扩展其功能。Role Strategy Plugin 是一个管理 Jenkins 角色的社区插件。使用它,我们可以为用户和组创建不同的访问级别控制:

Jenkins 的角色策略插件

角色通常需要与团队设置和业务要求保持一致。您可能希望根据您的要求进行微调。

阅读更多请访问 wiki.jenkins.io/display/JENKINS/Role+Strategy+Plugin

Jenkins 的 TLS/SSL

默认情况下,Jenkins 作为普通的 HTTP 运行。要启用 HTTPS,我们可以使用反向代理,例如 Nginx,在 Jenkins 前端充当 HTTPS 服务。

有关参考,请访问 www.digitalocean.com/community/tutorials/how-to-configure-jenkins-with-ssl-using-an-nginx-reverse-proxy

Jenkins 的加密和数据安全

我们正在使用 Jenkins 的默认凭据功能。这将把密钥和密码存储在本地文件系统中。还有不同的 Jenkins 插件可用于处理此问题,例如 wiki.jenkins.io/display/JENKINS/Credentials+Plugin

以下截图是一个参考,显示了我们如何在 Jenkins 中添加凭据:

Rundeck 的 RBAC

Rundeck 也提供了 RBAC,就像 Ansible Tower 一样。与 Tower 不同,在 /etc/rundeck/ 中我们必须使用 YAML 配置文件进行配置。

以下代码片段是创建管理员用户策略的示例:

description: Admin, all access.
context:
 application: 'rundeck'
for:
 resource: 
 - allow: '*' # allow create of projects 
 project: 
 - allow: '*' # allow view/admin of all projects
 project_acl: 
 - allow: '*' # allow all project-level ACL policies
 storage: 
 - allow: '*' # allow read/create/update/delete for all /keys/* storage content 
by: group: admin 

有关创建不同策略的更多信息,请访问 rundeck.org/docs/administration/access-control-policy.html

Rundeck 的 HTTP/TLS

可以使用 /etc/rundeck/ssl/ssl.properties 文件为 Rundeck 配置 HTTPS:

keystore=/etc/rundeck/ssl/keystore
keystore.password=adminadmin
key.password=adminadmin
truststore=/etc/rundeck/ssl/truststore
truststore.password=adminadmin

有关更多信息,请访问 rundeck.org/docs/administration/configuring-ssl.html

Rundeck 的加密和数据安全

凭证,例如密码和密钥,存储在本地存储中并加密,使用 Rundeck 密钥存储进行加密和解密。这还支持使用不同的密钥存储插件来使用密钥存储,例如存储转换器插件。对存储设施中的密钥的访问受到 访问控制列表 (ACL) 策略的限制。

playbooks 的输出

一旦自动化作业完成,我们想知道发生了什么。它们是否完全运行,是否遇到任何错误等。我们想知道在哪里可以看到执行 playbooks 的输出以及是否创建了任何其他日志。

Ansible Tower 的报告管理

默认情况下,Ansible Tower 本身是 playbooks、作业执行和清单收集状态的报告平台。Ansible Tower 仪表板提供了项目总数、清单、主机和作业状态的概览。

输出可以在仪表板、标准输出中使用,也可以通过 REST API 获取,并且我们也可以通过 tower-cli 命令行工具获取,这只是一个用于与 REST API 交互的预构建命令行工具。

Ansible Tower 仪表板

Ansible Tower 的标准输出

Ansible Tower REST API

Jenkins 的报告管理

Jenkins 提供了用于管理报告的标准输出和 REST API。Jenkins 拥有一个庞大的社区,有多个可用的插件,例如 HTML Publisher Plugin 和 Cucumber Reports Plugin。

这些插件提供了输出的可视化表示:

Jenkins 作业控制台的标准输出

Rundeck 的报告管理

Rundeck 还提供了标准输出和 REST API 来查询结果:

可以通过 stdout、TXT 和 HTML 格式消耗的作业输出

作业的调度

在 Ansible Tower 中,作业的调度简单而直接。对于一个作业,你可以指定一个时间表,选项大多类似于 cron。

例如,你可以说你有一个每天扫描的模板,并希望在未来三个月的每天上午 4 点执行它。这种类型的时间表使我们的元自动化非常灵活和强大。

警报、通知和 webhook

Tower 支持多种方式的警报和通知用户按配置。甚至可以配置它使用 webhook 向您选择的 URL 发送 HTTP POST 请求:

使用 slack webhook 的 Ansible Tower 通知

摘要

我们快速浏览了一些 IT 自动化和调度软件。我们的主要目的是介绍该软件并突出其一些常见功能。

这些功能包括以下内容:

  • 为我们的秘密提供加密

  • 根据我们的时间表要求运行

  • 获得良好报告的能力

我们已经了解了允许我们重复使用和创建出色 playbooks 的 Ansible 角色。结合这些功能,我们有一个完整的自动化系统准备好了。我们不仅能够随意运行我们的任务和作业多次,还会得到关于它们运行情况的更新。此外,由于我们的任务在受保护的服务器上运行,因此重要的是我们分享的用于运行的秘密也是安全的。

在下一章中,我们将不再考虑 Ansible 自动化的机制,而是直接思考特定情况下的安全自动化。自动化服务器的补丁是最明显、可能也是最受欢迎的需求。我们将应用安全自动化技术和方法来设置一个强化的 WordPress,并启用加密备份。

使用加密自动备份的强化 WordPress

现在基本设置已完成,让我们逐个讨论各种安全自动化场景,并一一查看它们。

每个人都会同意,建立一个安全的网站并保持其安全性是一个相当普遍的安全要求。由于这是如此普遍,因此对于那些负责构建和管理网站以保持安全的人来说,查看特定情景可能是有用的。

您是否知道,根据维基百科的数据,前 1000 万个网站中有 27.5%使用 WordPress?根据另一项统计数据,整个网络上所有已知软件中有 58.7%的网站在运行 WordPress。

如果有这么多,那么一种自动化的安全方式来设置和维护 WordPress 对一些读者应该是有用的。

即使 WordPress 不是您非常感兴趣的内容,也请记住,设置和保护 LAMP/LEMP 堆栈应用程序的整体步骤是普遍适用的。

对我们来说,使用加密自动备份的强化 WordPress 可以分解为以下步骤:

  1. 设置带有安全措施的 Linux/Windows 服务器。

  2. 设置 Web 服务器(Linux 上的 Apache/Nginx 和 Windows 上的 IIS)。

  3. 在同一主机上设置数据库服务器(MySQL)。

  4. 使用名为WP-CLI的命令行实用程序设置 WordPress。

  5. 为网站文件和数据库设置增量、加密和最重要的自动化备份。

在本章中,我们将使用 Ansible playbook 和 roles 完成所有这些。我们将假设我们计划部署 WordPress 网站的服务器已经启动并运行,并且我们能够连接到它。我们将备份存储在已经配置好的 AWS S3 存储桶中,其中访问密钥和秘密访问密钥已经提供。

我们将讨论以下主题:

  • WordPress 的 CLI

  • 为什么选择 Ansible 进行此设置?

  • 逐步完成 WordPress 安装

  • 设置 Apache2 Web 服务器

  • 如果您不想自己构建,那么 Trellis 堆栈呢?

  • 我们为什么要使用 Trellis,并且何时使用它是一个好主意?

  • 使用 Let's Encrypt 启用 TLS/SSL

  • Windows 上的 WordPress

WordPress 的 CLI

我们将使用一个名为 WP-CLI 的工具,它允许我们在 WordPress 中执行许多传统上需要使用 Web 浏览器的操作。

WP-CLI 是 WordPress 的 CLI。您可以更新插件、配置多站点安装等,而无需使用 Web 浏览器。有关 WP-CLI 的更多信息,请访问WP-CLI.org/,有关 WordPress,请访问wordpress.org/

例如,以下命令将下载并设置 WordPress:

wp core install # with some options such as url, title of the website etc. etc.

完整示例可在developer.WordPress.org/cli/commands/core/#examples找到:

wp core install --url=example.com --title=Example --admin_user=supervisor --admin_password=strongpassword [email protected]

此示例让我们一窥从 Ansible playbook 中调用 WP-CLI 工具的威力。

为什么选择 Ansible 进行此设置?

Ansible 专为安全自动化和硬化而设计。它使用 YAML 语法,帮助我们对重复任务的整个过程进行编码。通过使用这个,我们可以使用角色和播放书自动化基础架构的持续交付和部署过程。

模块化方法使我们能够非常简单地执行任务。例如,运维团队可以编写一个播放书来设置 WordPress 站点,安全团队可以创建另一个角色,用于加固 WordPress 站点。

使用模块实现可重复性非常容易,并且输出是幂等的,这意味着可以为服务器、应用程序和基础架构创建标准。一些用例包括使用内部政策标准为组织创建基础镜像。

Ansible 使用 SSH 协议,默认情况下使用加密传输和主机加密进行保护。而且,在处理不同类型的操作系统时不存在依赖性问题。它使用 Python 执行;根据我们的用例,这可以很容易地扩展。

逐步完成 WordPress 安装

在本节中,我们将继续完成 WordPress、所需的数据库服务器、硬化和备份的完整设置。我们选择的平台是 Linux(Ubuntu 16.04),使用 nginx Web 服务器和 PHP-FPM 作为 PHP 运行时。我们将使用 duply 设置备份,备份将存储在 AWS S3 中。

设置 nginx Web 服务器

设置 nginx 就像sudo apt-get install nginx这样简单,但是为我们的用例配置并管理配置的自动化方式是 Ansible 的强大之处。让我们看一下播放书中 nginx 角色的以下片段:

- name: adding nginx signing key
  apt_key:
    url: http://nginx.org/keys/nginx_signing.key
    state: present

- name: adding sources.list deb url for nginx
  lineinfile:
    dest: /etc/apt/sources.list
    line: "deb http://nginx.org/packages/mainline/ubuntu/ trusty nginx"

- name: update the cache and install nginx server
  apt:
    name: nginx
    update_cache: yes
    state: present

- name: updating customized templates for nginx configuration
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dst }}"

  with_items:
    - { src: "templates/defautlt.conf.j2", dst: "/etc/nginx/conf.d/default.conf" }    

  notify
    - start nginx
    - startup nginx

在上述代码片段中,我们正在添加签名密钥,然后添加存储库,然后进行安装。这样可以确保我们在从存储库下载软件包时也可以执行完整性检查。

然后,我们使用 Jinja2 模板执行配置更改,这些更改可以在服务器更新之前预定义在我们的配置中。

设置先决条件

要设置 WordPress CMS,我们需要安装数据库和 PHP,因此我们将安装 MySQL 作为数据库,以及 PHP-FPM 用于处理。

设置 MySQL 数据库

我们已经在前一章中看到了如何设置 MySQL。在这里,我们将看到如何为 WordPress 应用程序创建新用户和数据库。然后,我们将通过 Ansible 模块应用硬化步骤:

- name: create WordPress database
    mysql_db:
      name: "{{ WordPress_database_name }}"
      state: present
      login_user: root
      login_password: "{{ mysql_root_password }}"

- name: create WordPress database user
    mysql_user:
      name: "{{ WordPress_database_username }}"
      password: "{{ WordPress_database_password }}"
      priv: '"{{ WordPress_database_name }}".*:ALL'
      state: present
      login_user: root
      login_password: "{{ mysql_root_password }}"

上述代码片段描述了使用mysql_dbmysql_user模块创建新数据库和用户,并分别将该用户赋予 WordPress 应用数据库完全权限。

为 WordPress 设置安装 PHP

以下代码片段使用不同的模块来执行 PHP 和其他所需包的安装。然后,它使用 replace 模块更新 PHP-FPM 配置。最后,它还使用 template 模块更新 nginx 配置以更新 PHP-FPM 处理,并重新启动服务以应用更改:

- name: installing php
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - php
    - php-curl
    - php-fpm
    - php-mysql
    - php-xmlrpc

- name: configuring php.ini for php processor
  replace:
    path: /etc/php5/fpm/php.ini
    regex: ';cgi.fix_pathinfo=1'
    replace: 'cgi.fix_pathinfo=0'
    backup: yes

- name: enable and restart the php fpm service
  service:
    name: php7.0-fpm
    enabled: yes
    state: restarted

- name: update the nginx configuration to support php-fpm
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dst }}"

  with_items:
    - { src: "defautlt.conf.j2", dst: "/etc/nginx/conf.d/default.conf" }

- name: restart the nginx
  service:
    state: restarted
    name: nginx

使用 WP-CLI 安装 WordPress

以下代码片段将安装和设置 WordPress,以便它能够正常运行:

- debug:
  msg: ensure you have installed lamp (or) lemp stack

- name: downloading WordPress cli aka wp-cli
  get_url:
    url: https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
    dest: /usr/local/bin/wp
    mode: 0755

- name: download latest WordPress locally
  command: wp core download
  become_user: "{{ new_user_name }}"
  args:
    chdir: /var/www/html/

- name: WordPress site configuration
  command: "wp core config --dbname={{ WordPress_database_name }} --dbuser={{ WordPress_database_username }} --dbpass={{ WordPress_database_password }}

- name: information for WordPress site
  command: "wp core install --url={{ WordPress_site_name }} --title={{ WordPress_site_title }} --admin_user={{ WordPress_admin_username }} --admin_password={{ WordPress_admin_password }} --admin_email={{ WordPress_admin_email }}"

强化 SSH 服务

这将是一个更传统的方法,采用现代化的自动化方法,使用 Ansible。这里包括的一些项目有:

  • 禁用 root 用户登录,并创建一个不同的用户,如果需要,提供 sudo 权限:
    - name: create new user
      user:
        name: "{{ new_user_name }}"
        password: "{{ new_user_password }}"
        shell: /bin/bash
        groups: sudo
        append: yes
  • 使用基于密钥的身份验证登录。与基于密码的身份验证不同,我们可以生成 SSH 密钥并将公钥添加到授权密钥中:
    - name: add ssh key for new user
      authorized_key:
        user: "{{ new_user_name }}"
        key: "{{ lookup('file', '/home/user/.ssh/id_rsa.pub') }}"
        state: present
  • 使用 SSH 配置文件进行一些配置调整;例如,PermitRootLoginPubkeyAuthenticationPasswordAuthentication
    - name: ssh configuration tweaks
      lineinfile:
        dest: /etc/ssh/sshd_config
        state: present
        line: "{{ item }}"
        backups: yes

      with_items:
        - "PermitRootLogin no"
        - "PasswordAuthentication no"

      notify:
        - restart ssh

下面的操作手册将由 dev-sec 团队提供更多关于 SSH 强化的高级功能:github.com/dev-sec/ansible-ssh-hardening

强化数据库服务

我们已经看到如何设置数据库。以下代码片段显示了如何通过将其绑定到 localhost 和与应用程序交互所需的接口来加固 MySQL 服务。然后,它移除了匿名用户和测试数据库:

- name: delete anonymous mysql user for localhost
  mysql_user:
    user: ""
    state: absent
    login_password: "{{ mysql_root_password }}"
    login_user: root

- name: secure mysql root user
  mysql_user:
    user: "root"
    password: "{{ mysql_root_password }}"
    host: "{{ item }}"
    login_password: "{{ mysql_root_password }}"
    login_user: root

  with_items:
    - 127.0.0.1
    - localhost
    - ::1
    - "{{ ansible_fqdn }}"

- name: removes mysql test database
  mysql_db:
    db: test
    state: absent
    login_password: "{{ mysql_root_password }}"
    login_user: root

强化 nginx

在这里,我们可以开始查看如何禁用服务器标记以不显示版本信息,添加诸如 X-XSS-Protection 之类的头部,以及许多其他配置调整。这些大多数更改都是通过配置更改完成的,Ansible 允许我们根据用户需求对这些更改进行版本控制和自动化:

  • 可以通过在配置中添加 server_tokens off; 来阻止 nginx 服务器版本信息

  • add_header X-XSS-Protection "1; mode=block"; 将启用跨站点脚本 (XSS) 过滤器

  • 可以通过添加 ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 来禁用 SSLv3

  • 这个列表可能会相当长,根据使用情况和场景而定:

以下代码片段包含了用于更新强化的 nginx 配置更改的 nginx 配置模板:

    - name: update the hardened nginx configuration changes
      template:
        src: "hardened-nginx-config.j2"
        dest: "/etc/nginx/sites-available/default"

      notify:
        - restart nginx

Mozilla 在 wiki.mozilla.org/Security/Server_Side_TLS 上提供了更新的有关 SSL/TLS 指导的网页。该指导提供了关于使用什么密码套件以及其他安全措施的建议。此外,如果您信任他们的判断,您还可以使用他们的 SSL/TLS 配置生成器快速生成您的 Web 服务器配置的配置。欲了解更多信息,请访问 mozilla.github.io/server-side-tls/ssl-config-generator/

无论您决定使用哪种配置,模板都需要命名为 hardened-nginx-config.j2

加固 WordPress

这包括对 WordPress 安全配置错误的基本检查。其中一些包括:

  • 目录和文件权限:
    - name: update the file permissions
      file:
        path: "{{ WordPress_install_directory }}"
        recurse: yes
        owner: "{{ new_user_name }}"
        group: www-data

    - name: updating file and directory permissions
      shell: "{{ item }}"

      with_items:
        - "find {{ WordPress_install_directory }} -type d -exec chmod
         755 {} \;"
        - "find {{ WordPress_install_directory }} -type f -exec chmod 
        644 {} \;"
  • 用户名和附件枚举阻止。以下代码片段是 nginx 配置的一部分:
    # Username enumeration block
    if ($args ~ "^/?author=([0-9]*)"){
        return 403;
    }

    # Attachment enumeration block
    if ($query_string ~ "attachment_id=([0-9]*)"){
        return 403;
    }
  • 禁止在 WordPress 编辑器中编辑文件:
    - name: update the WordPress configuration
      lineinfile:
        path: /var/www/html/wp-config.php
        line: "{{ item }}"

      with_items:
        - define('FS_METHOD', 'direct');
        - define('DISALLOW_FILE_EDIT', true);

随着配置的更改和更新,我们可以添加许多其他检查。

加固主机防火墙服务

以下代码片段是用于安装和配置简易防火墙UFW)及其所需的服务和规则。Ansible 甚至有一个用于 UFW 的模块,因此以下片段以安装此模块并启用日志记录开始。接着它添加了默认策略,比如默认拒绝所有入站流量并允许出站流量。

然后将添加 SSH、HTTP 和 HTTPS 服务以允许进入。这些选项是完全可配置的,根据需要。然后它将启用并添加到启动程序中以应用更改:

- name: installing ufw package
  apt:
    name: "ufw"
    update_cache: yes
    state: present

- name: enable ufw logging
  ufw:
    logging: on

- name: default ufw setting
  ufw:
    direction: "{{ item.direction }}"
    policy: "{{ item.policy }}"

  with_items:
    - { direction: 'incoming', policy: 'deny' }
    - { direction: 'outgoing', policy: 'allow' }

- name: allow required ports to access server
  ufw:
    rule: "{{ item.policy }}"
    port: "{{ item.port }}"
    proto: "{{ item.protocol }}"

  with_items:
    - { port: "22", protocol: "tcp", policy: "allow" }
    - { port: "80", protocol: "tcp", policy: "allow" }
    - { port: "443", protocol: "tcp", policy: "allow" }

- name: enable ufw
  ufw:
    state: enabled

- name: restart ufw and add to start up programs
  service:
    name: ufw
    state: restarted
    enabled: yes

在 AWS S3 中设置自动化的加密备份

备份始终是我们大多数人觉得应该完成的事情,但它们似乎相当繁琐。多年来,人们已经做了大量工作,以确保我们可以有足够简单的方式来备份和恢复我们的数据。

在当今这个时代,一个出色的备份解决方案/软件应该能够执行以下操作:

特性 备注
自动化 自动化允许围绕其进行流程
增量 尽管整体存储成本较低,但如果我们想要每五分钟备份一次,那么已更改的内容应该被备份
离开我们的服务器之前加密 这是为了确保数据在静止和运动中的安全性
便宜 尽管我们关心我们的数据,但一个好的备份解决方案会比需要备份的服务器便宜得多

对于我们的备份解决方案,我们将选择以下堆栈:

软件 Duply - 一个包装在 duplicity 上的包装器,是一个 Python 脚本
存储 尽管 duply 提供了许多后端,但它与 AWS S3 非常兼容
加密 通过使用 GPG,我们可以使用非对称的公钥和私钥对

以下代码片段是为了在服务器和 AWS S3 之间设置 duply 进行加密的自动化备份:

- name: installing duply
  apt:
    name: "{{ item }}"
    update_cache: yes
    state: present

  with_items:
    - python-boto
    - duply

- name: check if we already have backup directory
  stat:
    path: "/root/.duply/{{ new_backup_name }}"
  register: duply_dir_stats

- name: create backup directories
  shell: duply {{ new_backup_name }} create
  when: duply_dir_stats.stat.exists == False

- name: update the duply configuration
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"

  with_items:
    - { src: conf.j2, dest: /root/.duply/{{ new_backup_name }}/conf }
    - { src: exclude.j2, dest: /root/.duply/{{ new_backup_name }}/exclude }

- name: create cron job for automated backups
  template:
    src: duply-backup.j2
    dest: /etc/cron.hourly/duply-backup

使用 Ansible Tower 对 Ubuntu 16.04 服务器执行 playbook

一旦我们准备好 playbook 并根据需要更新变量,我们就可以继续执行 playbook。在那之前,我们必须在 Ansible Tower 中创建模板来执行此操作。

用于 WordPress 设置 playbook 的 Ansible Tower 作业模板

WordPress 设置 playbook 作业执行

使用 HTTPS 的 WordPress 网站

安全地自动化 WordPress 更新

以下代码片段是用于运行备份并更新 WordPress 核心、主题和插件的。可以通过 Ansible Tower 作业每天定时执行:

- name: running backup using duply
  command: /etc/cron.hourly/duply-backup

- name: updating WordPress core
  command: wp core update
  register: wp_core_update_output
  ignore_errors: yes

- name: wp core update output
  debug:
    msg: "{{ wp_core_update_output.stdout }}"

- name: updating WordPress themes
  command: wp theme update --all
  register: wp_theme_update_output
  ignore_errors: yes

- name: wp themes update output
  debug:
    msg: "{{ wp_theme_update_output.stdout }}"

- name: updating WordPress plugins
  command: wp plugin update --all
  register: wp_plugin_update_output
  ignore_errors: yes

- name: wp plugins update output
  debug:
    msg: "{{ wp_plugin_update_output.stdout }}"

通过 Ansible Tower 进行每日更新的调度

Ansible Tower 允许我们安排自动运行对服务器的作业。我们可以在模板中配置开始日期和重复频率以执行 playbook。

通过 Ansible Tower 进行自动化 WordPress 更新的作业调度

否则,我们可以使用 cron 作业模板每天执行此操作,并在部署 WordPress 设置时添加此模板:

#!/bin/bash

/etc/cron.hourly/duply-backup
wp core update
wp theme update --all
wp plugin update --all

设置 Apache2 web 服务器

我们在我们的 LEMP 栈设置中已经见过这个,它非常相似。但是在这里,我们必须使用与 WordPress 一起工作的所需模块。以下代码片段显示了我们如何使用模板来执行服务器上的配置更新:

- name: installing apache2 server
  apt:
    name: "apache2"
    update_cache: yes
    state: present

- name: updating customized templates for apache2 configuration
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dst }}"
    mode: 0644

  with_tems:
    - { src: apache2.conf.j2, dst: /etc/apache2/conf.d/apache2.conf }
    - { src: 000-default.conf.j2, dst: /etc/apache2/sites-available/000-default.conf }
    - { src: default-ssl.conf.j2, dst: /etc/apache2/sites-available/default-ssl.conf }

- name: adding custom link for sites-enabled from sites-available
  file:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    state: link

  with_items:
    - { src: '/etc/apache2/sites-available/000-default.conf', dest: '/etc/apache2/sites-enabled/000-default.conf' }
    - { src: '/etc/apache2/sites-available/default-ssl.conf', dest: '/etc/apache2/sites-enabled/default-ssl.conf' }

  notify:
    - start apache2
    - startup apache2

使用 Let's Encrypt 启用 TLS/SSL

我们可以使用 Let's Encrypt 提供的命令行工具以开放、自动化的方式获取免费的 SSL/TLS 证书。

该工具能够完全自动地读取和理解一个 nginx 虚拟主机文件,并生成相关的证书,不需要任何手动干预:

- name: adding certbot ppa
  apt_repository:
    repo: "ppa:certbot/certbot"

- name: install certbot
  apt:
    name: "{{ item }}"
    update_cache: yes
    state: present

  with_items:
    - python-certbot-nginx

- name: check if we have generated a cert already
  stat:
    path: "/etc/letsencrypt/live/{{ website_domain_name }}/fullchain.pem"
  register: cert_stats

- name: run certbot to generate the certificates
  shell: "certbot certonly --standalone -d {{ website_domain_name }} --email {{ service_admin_email }} --non-interactive --agree-tos"
  when: cert_stats.stat.exists == False

- name: configuring site files
  template:
    src: website.conf
    dest: "/etc/nginx/sites-available/{{ website_domain_name }}"

- name: restart nginx
  service:
    name: nginx
    state: restarted

Let's Encrypt 已成为在网站上启用 SSL/TLS 的一种极其流行和安全的方式。

到 2017 年 6 月底,Let's Encrypt 已经以自动方式发布了超过 1 亿个免费的 SSL/TLS 证书。有关更多信息,请访问 letsencrypt.org/2017/06/28/hundred-million-certs.html

如果你不想自己动手怎么办?Trellis 栈

Trellis 栈是开发团队为 WordPress 网站建立本地临时和生产环境设置的一种方式。

Trellis 是一个为 WordPress LEMP 栈设计的一组开源 MIT 许可的 Ansible playbook。

我们为什么要使用 Trellis,以及什么时候使用它是一个好主意?

Trellis 是一个完整的项目,基于各种工具,由 Ansible 组合在一起。在许多方面,它是使用本章节的 playbook 的一个更好的选择的替代品。

如果你预期要构建/开发、部署,然后维护 WordPress 网站或网站的生产环境,那么 Trellis 是一个不错的选择。

唯一的注意事项是,如果有团队进行开发和部署,则许多可用功能更有用。否则,堆栈是有偏见的,你可能会被一些你不喜欢的软件选择所困扰。

Windows 上的 WordPress

这是我们现在要执行的新事物之一。到目前为止,我们一直在 Linux 操作系统中设置东西。现在我们要在 Windows 操作系统中设置 IIS Web 服务器,这需要我们在 Windows 服务中启用WinRM功能以执行 Ansible playbook。

我们需要确保在控制机器上安装了pywinrm模块;我们可以通过执行以下pip命令来安装它:

pip install "pywinrm>=0.2.2"

如何在 Windows 中启用 WinRM

为了简化这个过程,Ansible 提供了一个 PowerShell 脚本,需要在 PowerShell 控制台中以管理员身份运行。从raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1下载 PowerShell 脚本。

在 Windows 机器上,以管理员身份打开命令提示符,并运行以下命令:

powershell.exe -File ConfigureRemotingForAnsible.ps1 -CertValidityDays 100

请确保在防火墙规则中为 Windows 机器打开了端口5986。有关 Windows 设置的更多参考信息,请访问docs.ansible.com/ansible/latest/intro_windows.html

运行 Ansible 针对 Windows 服务器

现在,让我们通过执行简单的 ping 模块来测试针对 Windows 服务器的情况。

首先,我们需要创建包括连接 Windows winrm服务选项的inventory文件:

[windows]
192.168.56.120 ansible_user=Administrator ansible_password=strongpassowrd ansible_connection=winrm ansible_winrm_server_cert_validation=ignore ansible_port=5986

要执行 Windows ping 模块,我们可以运行以下 Ansible 命令:

ansible -i inventory windows -m win_ping

要了解有关 Windows 中可用模块的不同可用模块的更多信息,请参阅docs.ansible.com/ansible/latest/list_of_windows_modules.html

使用 playbook 安装 IIS 服务器

以下代码片段解释了我们如何在 Windows 服务器操作系统中安装和启动 IIS 服务:

- name: Install and start IIS web server in Windows server
  hosts: winblows

  tasks:
    - name: Install IIS
      win_feature:
        name: "Web-Server"
        state: present
        restart: yes
        include_sub_features: yes
        include_management_tools: yes

我们将使用 Chocolatey(有关更多信息,请访问chocolatey.org/),这是 Windows 的软件包管理器,用于在 Windows 中进行高级安装和设置。

下一步是安装 Web 平台安装程序。

Microsoft Web 平台安装程序(Web PI)是一个免费工具,可轻松获取 Microsoft Web 平台的最新组件,包括Internet 信息服务IIS),SQL Server Express,.NET Framework 和 Visual Web 开发人员工具。有关更多信息,请访问www.microsoft.com/web/downloads/platform.aspx

安装完毕后,我们可以使用此方法安装 MySQL 和 WordPress:

以下剧本运行了由gist.github.com/chrisloweau/8a15516d551a87b096620134c3624b73创建的 PowerShell 脚本。有关 PowerShell 脚本的更多详细信息,请参阅www.lowefamily.com.au/2017/04/11/how-to-install-wordpress-on-windows-server-2016/

此设置需要一些先决条件。其中包括设置 PowerShell 执行策略和支持的 Windows 版本。

  • 首先,我们需要运行以下命令设置执行策略:
 Set-ExecutionPolicy RemoteSigned CurrentUser
  • 此脚本仅支持 Windows Server 2016 操作系统和 Windows 10。

以下 Ansible 剧本正在执行 PowerShell 脚本,以在 Windows 操作系统中设置 WordPress。

- name: Windows Wordpress Setup Playbook
  hosts: winblows

  tasks:
    - name: download wordpress setup script
      win_get_url:
        url: https://gist.githubusercontent.com/chrisloweau/8a15516d551a87b096620134c3624b73/raw/b7a94e025b3cbf11c3f183d20e87c07de86124a3/wordpress-install.ps1
        dest: ~\Downloads\wordpress-install.ps1

    # This requires `Set-ExecutionPolicy RemoteSigned CurrentUser` to All
    - name: running windows wordpress script
      win_shell: ~\Downloads\wordpress-install.ps1
      args:
        chdir: ~\Downloads\wordpress-install.ps1
      register: output

    - debug:
        msg: "{{ output.stdout }}"
  • 执行后,它会返回类似以下的输出。然后我们可以导航到 IP 地址并按照说明设置 WordPress 的最终配置。
Installation Complete!

MySQL Accounts
       root = 2*Bb!o4#4T2yy/*44ngb
  wordpress = B*OGGrg{{ghr$35nGt4rU

Connect your web browser to http://192.168.56.100/ to complete this WordPress
installation.

摘要

这一章主要讲解了 WordPress。我们使用 Ansible 默认创建了一个相当安全的 WordPress 安装。通过改变数据库、Web 服务器和 WordPress 的默认值,我们利用了使用 Ansible 剧本编码安全知识的能力。此外,通过设置自动、增量、加密备份,我们实现了对最坏情况的弹性和连续性。

我们简要介绍了如何启用 Windows 以便与 Ansible 一起使用。

在下一章中,我们将研究 Elastic Stack 用于设置集中式日志基础设施。这不仅适用于存储各种日志,而且还会在我们受到攻击时提醒和通知我们。我们还将学习如何部署无服务器防御以自动阻止攻击者。

日志监控和无服务器自动防御(AWS 中的 Elastic Stack)

日志监控是考虑安全自动化的理想场所。要使监视有效,需要发生一些事情。我们应该能够将来自不同设备的日志移动到一个中心位置。我们应该能够理解什么是常规日志条目,以及可能是攻击的内容。我们应该能够存储日志,并对其进行诸如聚合、标准化以及最终分析等操作。

但是,在深入设置堆栈并使用 Elastic Stack 构建集中式日志记录和监控之前,我们需要了解一些关于为什么需要使用和自动设置来防御接近实时攻击的原因。成为万事通是困难的。传统的日志记录系统发现很难为所有应用程序、系统和设备记录日志。各种时间格式、日志输出格式等等使得这项任务变得非常复杂。

最大的障碍是找到一种方法能够集中日志。这妨碍了能够有效地实时或接近实时处理日志条目。

以下是一些问题点:

  • 访问通常很困难

  • 需要高度专业的挖掘数据技能

  • 日志很难找到

  • 日志数据庞大

在本章中,我们将讨论以下主题:

  • 安装 Elastic Stack 进行日志监控

  • 在服务器上安装 Beats

  • 设置和配置警报

  • 设置 AWS Lambda 终端点以进行自动化防御

Elastic Stack 简介

Elastic Stack 是 Elastic 公司推出的一组开源产品。它可以从任何类型的来源和任何格式的数据中提取数据,并实时搜索、分析和可视化该数据。它由四个主要组件组成,如下:

  • Elasticsearch

  • Logstash

  • Kibana

  • 节拍

图片

Elastic Stack 架构概述(图片来源:https://www.elastic.co/blog/beats-1-0-0)

它帮助用户/管理员以(接近)实时的方式收集、分析和可视化数据。每个模块根据您的用例和环境进行调整。

Elasticsearch

Elasticsearch 是一个分布式的、RESTful 的搜索和分析引擎,能够解决越来越多的使用案例。作为 Elastic Stack 的核心,它集中存储您的数据,以便您可以发现预期的内容并发现意外情况

Elastic Stack 的主要优点:

  • 分布式和高可用搜索引擎,用 Java 编写,使用 Groovy

  • 基于 Lucene 构建

  • 多租户,具有多种类型和一组 API

  • 面向文档的,提供(接近)实时搜索

Logstash

Logstash 是一个开源的、服务器端的数据处理管道,它从多种来源摄取数据,同时对其进行转换,然后将其发送到您喜欢的 stash

只是强调 Logstash 是:

  • 一个用 Ruby 编写的管理事件和日志的工具

  • 所有类型日志的集中式数据处理

  • 包括以下三个主要组件:

    • 输入:传递日志以将其处理为机器可理解的格式

    • 过滤器:一组条件,用于对事件执行特定操作

    • 输出:已处理事件/日志的决策者

Kibana

Kibana 让你可以可视化你的 Elasticsearch 数据并导航 Elastic Stack,这样你就可以做任何事情,从了解为什么在凌晨 2 点会被叫醒到理解雨水可能对你的季度数据造成的影响。

Kibana 的功能列表:

  • 强大的前端仪表板是用 JavaScript 编写的

  • 基于浏览器的 Elasticsearch 分析和搜索仪表板

  • 一个灵活的分析和可视化平台

  • 实时以图表、图形、计数、地图等形式提供数据

Beats

Beats 是单一用途数据船的平台。它们安装为轻量级代理,并将数据从数百或数千台机器发送到 Logstash 或 Elasticsearch。

Beats 是:

  • 为 Elasticsearch 和 Logstash 提供轻量级船员

  • 捕获各种运营数据,比如日志或网络数据包

  • 它们可以将日志发送到 Elasticsearch 或 Logstash

不同类型的 Beats 如下所示:

  • Libbeat:用于创建新 Beats 的 Go 框架

  • Packetbeat:窥探您的线路数据

  • Filebeat:轻量级日志转发器到 Logstash 和 Elasticsearch

  • Winlogbeat:发送 Windows 事件日志,以及许多其他由社区提供的 Beats

为什么我们应该使用 Elastic Stack 进行安全监控和警报?

Elastic Stack 解决了我们之前讨论过的大部分问题,比如:

  • 能够存储大量数据

  • 能够理解和读取各种日志格式

  • 能够将日志信息从各种设备以近乎实时的方式发送到一个中央位置

  • 日志分析的可视化仪表板

设置 Elastic Stack 的先决条件

让我们从先决条件开始。在这里,我们使用 debconf 来为交互式输入添加值。然后我们安装 Java、nginx 和其他必需的软件包:

- name: install python 2
  raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)

- name: accepting oracle java license agreement
  debconf:
    name: 'oracle-java8-installer'
    question: 'shared/accepted-oracle-license-v1-1'
    value: 'true'
    vtype: 'select'

- name: adding ppa repo for oracle java by webupd8team
  apt_repository:
    repo: 'ppa:webupd8team/java'
    state: present
    update_cache: yes

- name: installing java nginx apache2-utils and git
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - python-software-properties
    - oracle-java8-installer
    - nginx
    - apache2-utils
    - python-pip
    - python-passlib

设置 Elastic Stack

栈是以下组合:

  • Elasticsearch 服务

  • Logstash 服务

  • Kibana 服务

  • 所有设备上的 Beats 服务

这个 Elastic Stack 可以以不同的方式设置。在本章中,我们将在单台机器上设置 Elasticsearch、Logstash 和 Kibana。

这是主要的日志收集机器:

  • 它至少需要 4 GB 的 RAM,因为我们在一台机器上为三个服务(Elasticsearch、Logstash 和 Kibana)提供服务

  • 它需要至少 20 GB 的磁盘空间,并根据您的日志大小增加磁盘空间

Logstash 集成

Logstash 为以下内容提供了非常大量的集成支持:

  • 输入:输入插件使得 Logstash 能够读取特定事件源。输入插件有文件、lumberjack、s3、Beats、stdin 等等。

  • 过滤器:过滤器插件对事件进行中间处理。根据事件的特征,通常会有条件地应用过滤器。

  • 输出:输出插件将事件数据发送到特定目的地。输出是事件管道中的最后阶段。输出插件包括 Elasticsearch、电子邮件、标准输出、s3、文件、HTTP 等等。

Kibana

Kibana 默认具有不同类型的插件和集成,以及社区提供的插件,可在www.elastic.co/guide/en/kibana/current/known-plugins.html找到。

ElastAlert

ElastAlert 是一个 Python 工具,还捆绑了不同类型的集成,用于支持警报和通知。其中一些包括命令、电子邮件、JIRA、OpsGenie、AWS SNS、HipChat、Slack、Telegram 等。它还提供了一种模块化的方法来创建我们自己的集成。

安装 Elasticsearch

从存储库安装 Elasticsearch,并将其添加到启动程序:

- name: adding elastic gpg key for elasticsearch
  apt_key:
    url: "https://artifacts.elastic.co/GPG-KEY-elasticsearch"
    state: present

- name: adding the elastic repository
  apt_repository:
    repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
    state: present

- name: installing elasticsearch
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - elasticsearch

- name: adding elasticsearch to the startup programs
  service:
    name: elasticsearch
    enabled: yes

  notify:
    - start elasticsearch

配置 Elasticsearch 集群所需的设置。另外,为 Elasticsearch 集群备份和快照创建一个备份目录。为 Elasticsearch 集群设置 JVM 选项。

- name: creating elasticsearch backup repo directory at {{ elasticsearch_backups_repo_path }}
  file:
    path: "{{ elasticsearch_backups_repo_path }}"
    state: directory
    mode: 0755
    owner: elasticsearch
    group: elasticsearch

- name: configuring elasticsearch.yml file
  template:
    src: "{{ item.src }}"
    dest: /etc/elasticsearch/"{{ item.dst }}"

  with_items:
    - { src: 'elasticsearch.yml.j2', dst: 'elasticsearch.yml' }
    - { src: 'jvm.options.j2', dst: 'jvm.options' }

  notify:
    - restart elasticsearch

通知部分将触发 重启 elasticsearch 处理程序,处理程序文件如下所示。一旦在处理程序目录中创建了处理程序,我们可以在任务中的任何地方使用处理程序:

- name: start elasticsearch
  service:
    name: elasticsearch
    state: started

- name: restart elasticsearch
  service:
    name: elasticsearch
    state: restarted

安装 Logstash

从存储库安装 Logstash,并将其添加到启动程序:

- name: adding elastic gpg key for logstash
  apt_key:
    url: "https://artifacts.elastic.co/GPG-KEY-elasticsearch"
    state: present

- name: adding the elastic repository
  apt_repository:
    repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
    state: present

- name: installing logstash
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - logstash

- name: adding logstash to the startup programs
  service:
    name: logstash
    enabled: yes

  notify:
    - start logstash

配置 Logstash 服务的输入、输出和过滤器设置。这使得可以接收日志、处理日志并将日志发送到 Elasticsearch 集群:

- name: logstash configuration files
  template:
    src: "{{ item.src }}"
    dest: /etc/logstash/conf.d/"{{ item.dst }}"

  with_items:
    - { src: '02-beats-input.conf.j2', dst: '02-beats-input.conf' }
    - { src: '10-sshlog-filter.conf.j2', dst: '10-sshlog-filter.conf' }
    - { src: '11-weblog-filter.conf.j2', dst: '11-weblog-filter.conf' }
    - { src: '30-elasticsearch-output.conf.j2', dst: '10-elasticsearch-output.conf' }

  notify:
    - restart logstash

Logstash 配置

为了从不同系统接收日志,我们使用 Elastic 的 Beats 服务。以下配置用于将来自不同服务器的日志发送到 Logstash 服务器。Logstash 运行在端口 5044 上,我们可以使用 SSL 证书来确保日志通过加密通道传输:

# 02-beats-input.conf.j2
input {
    beats {
        port => 5044
        ssl => true
        ssl_certificate => "/etc/pki/tls/certs/logstash-forwarder.crt"
        ssl_key => "/etc/pki/tls/private/logstash-forwarder.key"
    }
}

以下配置用于使用 grok 过滤器解析系统 SSH 服务日志(auth.log)。同时还应用了 geoip 等过滤器,提供额外的国家、地点、经度、纬度等信息:

#10-sshlog-filter.conf.j2
filter {
    if [type] == "sshlog" {
        grok {
            match => [ "message", "%{SYSLOGTIMESTAMP:syslog_date} %{SYSLOGHOST:syslog_host} %{DATA:syslog_program}(?:\[%{POSINT}\])?: %{WORD:login} password for %{USERNAME:username} from %{IP:ip} %{GREEDYDATA}",
            "message", "%{SYSLOGTIMESTAMP:syslog_date} %{SYSLOGHOST:syslog_host} %{DATA:syslog_program}(?:\[%{POSINT}\])?: message repeated 2 times: \[ %{WORD:login} password for %{USERNAME:username} from %{IP:ip} %{GREEDYDATA}",
            "message", "%{SYSLOGTIMESTAMP:syslog_date} %{SYSLOGHOST:syslog_host} %{DATA:syslog_program}(?:\[%{POSINT}\])?: %{WORD:login} password for invalid user %{USERNAME:username} from %{IP:ip} %{GREEDYDATA}",
            "message", "%{SYSLOGTIMESTAMP:syslog_date} %{SYSLOGHOST:syslog_host} %{DATA:syslog_program}(?:\[%{POSINT}\])?: %{WORD:login} %{WORD:auth_method} for %{USERNAME:username} from %{IP:ip} %{GREEDYDATA}" ]
        }

        date {
            match => [ "timestamp", "dd/MMM/YYYY:HH:mm:ss Z" ]
            locale => en
        }

        geoip {
            source => "ip"
        }
    }
}

以下配置用于解析 Web 服务器日志(nginxapache2)。还将应用 geoipuseragent 过滤器。useragent 过滤器可帮助我们获取有关代理、操作系统类型、版本信息等的信息:

#11-weblog-filter.conf.j2
filter {
    if [type] == "weblog" {
        grok {
        match => { "message" => '%{IPORHOST:clientip} %{USER:ident} %{USER:auth} \[%{HTTPDATE:timestamp}\] "%{WORD:verb} %{DATA:request} HTTP/%{NUMBER:httpversion}" %{NUMBER:response:int} (?:-|%{NUMBER:bytes:int}) %{QS:referrer} %{QS:agent}' }
        }

        date {
        match => [ "timestamp", "dd/MMM/YYYY:HH:mm:ss Z" ]
        locale => en
        }

        geoip {
            source => "clientip"
        }

        useragent {
            source => "agent"
            target => "useragent"
        }
    }
}

以下配置将日志输出发送到 Elasticsearch 集群,并采用每日索引格式:

#30-elasticsearch-output.conf.j2
output {
    elasticsearch {
        hosts => ["localhost:9200"]
        manage_template => false
        index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}"
        document_type => "%{[@metadata][type]}"
    }
}

安装 Kibana

以下 Playbook 将安装 Kibana。默认情况下,我们不会对 Kibana 进行任何更改,因为它与 Elasticsearch 相配合:

- name: adding elastic gpg key for kibana
  apt_key:
    url: "https://artifacts.elastic.co/GPG-KEY-elasticsearch"
    state: present

- name: adding the elastic repository
  apt_repository:
    repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
    state: present

- name: installing kibana
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - kibana

- name: adding kibana to the startup programs
  service:
    name: kibana
    enabled: yes

  notify:
    - start kibana

默认情况下,Kibana 没有任何身份验证,X-Pack 是 Elastic 提供的商业插件,用于 RBAC(基于角色的访问控制)和安全性。此外,一些开源选项包括 readonlyrest.com/ 和 Search Guard (floragunn.com) 用于与 Elasticsearch 交互。强烈建议使用 TLS/SSL 和自定义身份验证和授权。一些开源选项包括 OAuth2 Proxy (github.com/bitly/oauth2_proxy) 和 Auth0 等。

配置 nginx 反向代理

以下配置是使用 nginx 反向代理启用 Kibana 的基本身份验证:

server {
    listen 80;
    server_name localhost;
    auth_basic "Restricted Access";
    auth_basic_user_file /etc/nginx/htpasswd.users;
    location / {
        proxy_pass http://localhost:5601;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}

设置和配置 nginx 服务如下所示:

#command: htpasswd -c /etc/nginx/htpasswd.users
- name: htpasswd generation
  htpasswd:
    path: "/etc/nginx/htpasswd.users"
    name: "{{ basic_auth_username }}"
    password: "{{ basic_auth_password }}"
    owner: root
    group: root
    mode: 0644

- name: nginx virtualhost configuration
  template:
    src: "templates/nginxdefault.j2"
    dest: "/etc/nginx/sites-available/default"

  notify:
    - restart nginx

安装 Beats 以将日志发送到 Elastic Stack

正如我们讨论的那样,Beats 有不同类型。在下面的 playbook 中,我们将安装 Filebeat,以将 SSH 和 web 服务器日志发送到 Elastic Stack:

- name: adding elastic gpg key for filebeat
  apt_key:
    url: "https://artifacts.elastic.co/GPG-KEY-elasticsearch"
    state: present

- name: adding the elastic repository
  apt_repository:
    repo: "deb https://artifacts.elastic.co/packages/5.x/apt stable main"
    state: present

- name: installing filebeat
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - apt-transport-https
    - filebeat

- name: adding filebeat to the startup programs
  service:
    name: filebeat
    enabled: yes

  notify:
    - start filebeat

现在我们可以配置 Filebeat,将 SSH 和 web 服务器日志发送到 Elastic Stack,以便实时处理和索引:

filebeat:
  prospectors:
    -
      paths:
        - /var/log/auth.log
        # - /var/log/syslog
        # - /var/log/*.log
      document_type: sshlog
    -
      paths:
        - /var/log/nginx/access.log
      document_type: weblog

  registry_file: /var/lib/filebeat/registry

output:
 logstash:
   hosts: ["{{ logstash_server_ip }}:5044"]
   bulk_max_size: 1024
   ssl:
    certificate_authorities: ["/etc/pki/tls/certs/logstash-forwarder.crt"]

logging:
 files:
   rotateeverybytes: 10485760 # = 10MB

用于警报的 ElastAlert

首先,我们需要安装设置 ElastAlert 的先决条件。然后我们将添加配置文件以根据规则执行警报:

- name: installing pre requisuites for elastalert
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - python-pip
    - python-dev
    - libffi-dev
    - libssl-dev
    - python-setuptools
    - build-essential

- name: installing elastalert
  pip:
    name: elastalert

- name: creating elastalert directories
  file: 
    path: "{{ item }}"
    state: directory
    mode: 0755

  with_items:
    - /opt/elastalert/rules
    - /opt/elastalert/config

- name: creating elastalert configuration
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dst }}"

  with_items:
    - { src: 'elastalert-config.j2', dst: '/opt/elastalert/config/config.yml' }
    - { src: 'elastalert-service.j2', dst: '/lib/systemd/system/elastalert.service' }
    - { src: 'elastalert-sshrule.j2', dst: '/opt/elastalert/rules/ssh-bruteforce.yml' }

- name: enable elastalert service
  service:
    name: elastalert
    state: started
    enabled: yes

我们还将创建一个简单的启动脚本,以便将 ElastAlert 用作系统服务:

[Unit]
Description=elastalert
After=multi-user.target

[Service]
Type=simple
WorkingDirectory=/opt/elastalert
ExecStart=/usr/local/bin/elastalert --config /opt/elastalert/config/config.yml

[Install]
WantedBy=multi-user.target

配置 Let's Encrypt 服务

我们可以使用 Let's Encrypt 提供的命令行工具以开放、自动化的方式获取免费的 SSL/TLS 证书。

该工具能够读取并理解 nginx 虚拟主机文件,并完全自动生成相关证书,无需任何手动干预:

- name: adding certbot ppa
  apt_repository:
    repo: "ppa:certbot/certbot"

- name: install certbot
  apt:
    name: "{{ item }}"
    update_cache: yes
    state: present

  with_items:
    - python-certbot-nginx

- name: check if we have generated a cert already
  stat:
    path: "/etc/letsencrypt/live/{{ website_domain_name }}/fullchain.pem"
    register: cert_stats

- name: run certbot to generate the certificates
  shell: "certbot certonly --standalone -d {{ website_domain_name }} --email {{ service_admin_email }} --non-interactive --agree-tos"
  when: cert_stats.stat.exists == False

- name: configuring site files
  template:
    src: website.conf
    dest: "/etc/nginx/sites-available/{{ website_domain_name }}"

- name: restart nginx
  service:
    name: nginx
    state: restarted

ElastAlert 规则配置

假设您已经安装了 Elastic Stack 并记录了 SSH 日志,请使用以下 ElastAlert 规则触发 SSH 攻击 IP 黑名单:

es_host: localhost
es_port: 9200
name: "SSH Bruteforce attack alert"
type: frequency
index: filebeat-*
num_events: 20
timeframe:
  minutes: 1
# For more info: http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html

filter:
- query:
    query_string:
      query: '_type:sshlog AND login:failed AND (username: "ubuntu" OR username: "root")'

alert:
  - slack:
      slack_webhook_url: "https://hooks.slack.com/services/xxxxx"
      slack_username_override: "attack-bot"
      slack_emoji_override: "robot_face"
  - command: ["/usr/bin/curl", "https://xxxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/zzzzzzzzzzzzzz/ip/inframonitor/%(ip)s"]

realert:
  minutes: 0

在上述示例规则中,大多数参数都是可配置的,根据使用情况而定。

欲了解更多参考,请访问 elastalert.readthedocs.io/en/latest/running_elastalert.html

Kibana 仪表板

我们可以将现有的仪表板文件(JSON 格式)导入到 Kibana 中,通过上传 JSON 文件来查看不同的模式。

在 Kibana 仪表板中创建索引

将现有的仪表板和可视化内容导入到 Kibana 仪表板

来自 SSH 和 web 服务器日志的攻击仪表板

自动化防御?

如果我们能够收到攻击的通知,我们可以进行以下设置和操作:

  • 调用 AWS Lambda 函数

  • 将攻击者的 IP 地址信息发送到此 AWS Lambda 函数端点

  • 使用部署在 Lambda 函数中的代码调用 VPC 网络访问列表 API,并阻止攻击者的 IP 地址

为了确保我们不会用攻击者的 IP 填满 ACL,我们可以将这种方法与 AWS DynamoDB 结合使用,将此信息存储一段时间并从阻止列表中删除。

在设置中使用的 AWS 服务

一旦检测到攻击,警报器会通过 HTTPS 请求将 IP 发送到黑名单 Lambda 端点。使用网络 ACL 阻止 IP,并在 DynamoDB 中维护其记录。如果 IP 已被阻止,则在 DynamoDB 中将为该规则的过期时间延长。

定期触发一个到期处理程序函数,从 DynamoDB 和 ACL 中相应地删除过期的规则。

DynamoDB

DynamoDB 是规则映射到其相应 ACL ID 的中央数据库。通过适当的 Lambda 函数将 IP 地址的规则添加到blacklist_ip表中,并从中删除。

黑名单 Lambda 函数

黑名单函数是设置的唯一暴露的端点。需要通过 HTTPS 请求将需要列入黑名单的任何 IP 提供给此函数。

HandleExpiry Lambda 函数

HandleExpiry 函数每分钟触发一次,并根据expirymin字段从 ACL 和 DynamoDB 中删除过期规则。

云监控

云监控定期触发 HandleExpiry Lambda 函数。默认情况下,该函数每分钟触发一次。

VPC 网络 ACL

VPC 网络 ACL 是 ACL 规则添加和删除的地方。在设置时必须配置 ACL ID。

设置

设置涉及以下步骤:

  • 获取 IAM 凭证

  • 在 DynamoDB 中创建一个表

  • 根据需求配置 Lambda 函数

  • 将代码部署到 AWS Lambda

  • 配置云监控定期调用

整个设置是自动化的,除了获取 IAM 凭证并根据需求配置函数之外。

配置

在部署之前可配置以下参数:

  • region:部署的 AWS 区域。这需要与 VPC 网络所在的区域相同。

  • accessToken:用于对黑名单端点进行身份验证的 accessToken。

  • aclLimit:ACL 可处理的规则数的最大限制。AWS 中默认的最大限制是 20。

  • ruleStartId:ACL 中规则的起始 ID。

  • aclID:规则将应用的网络的 ACL ID。

  • tableName:为每个要防御的 VPC 创建的唯一表名称。

  • ruleValidity:规则有效的持续时间,之后 IP 将被解除阻止。

config.js文件中配置以下内容:

module.exports = {
    region: "us-east-1",                                        // AWS Region to deploy in
    accessToken: "YOUR_R4NDOM_S3CR3T_ACCESS_TOKEN_GOES_HERE",   // Accesstoken to make requests to blacklist
    aclLimit: 20,                                               // Maximum number of acl rules
    ruleStartId: 10,                                            // Starting id for acl entries
    aclId: "YOUR_ACL_ID",                                       // AclId that you want to be managed
    tableName: "blacklist_ip",                                  // DynamoDB table that will be created
    ruleValidity: 5                                             // Validity of Blacklist rule in minutes 
}

确保至少根据您的设置修改aclIdaccessTokenregion。要修改 Lambda 部署配置,请使用serverless.yml文件:

...

functions:
  blacklist:
    handler: handler.blacklistip
    events:
     - http:
         path: blacklistip
         method: get

  handleexpiry:
    handler: handler.handleexpiry
    events:
     - schedule: rate(1 minute)

...

例如,可以使用 YML 文件修改到期函数触发的速率以及黑名单函数的端点 URL。但默认值已经是最佳的。

播放手册如下:

- name: installing node run time and npm
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - nodejs
    - npm

- name: installing serverless package
  npm:
    name: "{{ item }}"
    global: yes
    state: present

  with_items:
    - serverless
    - aws-sdk

- name: copy the setup files
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dst }}"

  with_items:
    - { src: 'config.js.j2', dst: '/opt/serverless/config.js' }
    - { src: 'handler.js.j2', dst: '/opt/serverless/handler.js' }
    - { src: 'iamRoleStatements.json.j2', dst: '/opt/serverless/iamRoleStatements.json' }
    - { src: 'initDb.js.j2', dst: '/opt/serverless/initDb.js' }
    - { src: 'serverless.yml.j2', dst: '/opt/serverless/serverless.yml' }
    - { src: 'aws-credentials.j2', dst: '~/.aws/credentials' }

- name: create dynamo db table
  command: node initDb.js
  args:
    chdir: /opt/serverless/

- name: deploy the serverless
  command: serverless deploy
  args:
    chdir: /opt/serverless/

目前 AWS Lambda 的设置是针对网络 ACL 封锁 IP 地址。这可以在其他 API 端点上重用,比如防火墙动态封锁列表和其他安全设备。

根据 AWS 文档,VPC 网络 ACL 规则限制设置为 20:docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Appendix_Limits.html#vpc-limits-nacls

使用方法 - 封锁 IP 地址

黑名单端点负责封锁 IP 地址。

请求

URL 看起来像以下内容:https://lambda_url/blacklistipaccessToken=ACCESS_TOKEN&ip=IP_ADDRESS

查询参数如下:

  • IP_ADDRESS:要封锁的 IP 地址

  • ACCESS_TOKEN:用于验证请求的accessToken

响应

响应是标准的 HTTP 状态码,如下所述:

状态码 主体 解释
200 已封锁 该 IP 已添加到黑名单
200 延长到期 黑名单规则的有效期已延长
400 错误请求 缺少必填字段
401 未经授权 accessToken 无效或丢失
500 规则限制已达到 已达到 ACL 规则限制

自动化防御 lambda 在行动

当 ElastAlert 检测到 SSH 暴力攻击时,它将触发对 lambda 端点的请求,提供攻击者的 IP 地址。然后我们的自动化防御平台将触发网络 ACL 封锁列表规则。这可以配置为阻止多长时间。

摘要

这是很多信息需要消化的。此外,我们对场景做出了很多假设。但是,如果这激发了您考虑将设备和服务器的各种日志组合到一个中央位置并启用自动警报和防御措施,那我们的工作就做得很好。

正如本章所示,安全自动化有点像管道工作。只要我们能够理解如何让一堆不同的系统相互通信,我们就可以将它们添加到我们的 playbooks 中。在许多情况下,Ansible 已经为我们提供了可用于使用和启动的模块。

现在我们已经激发了您对日志记录和攻击检测的兴趣,在下一章中,让我们深入了解设置自动化网络安全测试的所需。我们将选择功能强大且多才多艺的 OWASP ZAP 扫描仪和拦截代理,并使用它扫描和测试网站和 API。

使用 OWASP ZAP 进行自动化 Web 应用程序安全测试

OWASP Zed Attack Proxy(通常称为ZAP)是最受欢迎的网络应用安全测试工具之一。它具有许多功能,使其可用于手动安全测试;在一些调整和配置后,它也很好地适用于持续集成/持续交付CI/CD)环境。

有关该项目的更多详细信息可以在www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project找到。

开放式网络应用安全项目OWASP)是一个致力于改善软件安全性的全球性非营利慈善组织。在www.owasp.org了解更多关于 OWASP 项目和资源的信息。

OWASP ZAP 在一个包中包含许多不同的工具和功能。对于负责对 Web 应用程序进行安全测试的渗透测试员,以下功能至关重要:

功能 用例
拦截代理 这允许我们拦截浏览器中的请求和响应
主动扫描器 自动运行针对目标的网络安全扫描
被动扫描器 从使用蜘蛛工具下载的页面中获取有关安全问题的信息
蜘蛛 在 ZAP 可以攻击应用程序之前,它通过遍历所有可能的网页来创建应用程序的站点地图
REST API 允许 ZAP 在无头模式下运行,并控制运行自动扫描器、蜘蛛和获取结果

正如你可能已经猜到的,在本章中,为了进行安全自动化,我们将以无头模式调用 ZAP,并使用其提供的 API 接口来进行扫描和安全测试。

ZAP 是基于 Java 的软件。使用它的典型方式将涉及以下内容:

  • Java 运行时环境JRE)7 或更高版本安装在您选择的操作系统中(macOS、Windows、Linux)

  • 使用官方下载页面的软件包管理器、安装程序安装 ZAP

你可以在此处找到最新的更新稳定链接:github.com/zaproxy/zaproxy/wiki/Downloads

虽然我们可以构建一个执行此操作的操作手册,但开发者世界正在向 CI/CD 和持续安全的概念发展。一个可以在需要时引导稳定版本的 ZAP 的方法将是理想的。

实现这一目标的最佳方法是将 OWASP ZAP 用作容器。事实上,这是 Mozilla 在 CI/CD 管道中使用 ZAP 来验证每个发布的基线安全控制的设置方式。

如果您想知道 Mozilla 和 OWASP ZAP 之间的联系,Simon Bennetts 领导了 OWASP ZAP 项目并在 Mozilla 工作。 阅读他关于 ZAP 基线扫描的博客文章:blog.mozilla.org/security/2017/01/25/setting-a-baseline-for-web-security-controls/

安装 OWASP ZAP

在本章中,我们将使用 OWASP ZAP 作为一个容器,这需要在主机操作系统中运行容器运行时。 OWASP ZAP 团队每周通过 Docker Hub 发布 ZAP Docker 镜像。 根据标签拉取 Docker 镜像的方法在现代 DevOps 环境中很受欢迎,因此我们谈论与其相关的自动化是有意义的。

官方 ZAP 现在通过 Docker Hub 的 Docker 容器提供稳定版和每周发布版本:github.com/zaproxy/zaproxy/wiki/Docker

安装 Docker 运行时

Docker 是供开发人员和系统管理员构建、发布和运行分布式应用程序的开放平台,无论是在笔记本电脑、数据中心虚拟机还是云中。 要了解有关 Docker 的更多信息,请参阅 www.docker.com/what-docker

以下 Playbook 将在 Ubuntu 16.04 中安装 Docker Community Edition 软件:

- name: installing docker on ubuntu
  hosts: zap
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  become: yes
  vars:
    remote_user_name: ubuntu
    apt_repo_data: "deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable"
    apt_gpg_key: https://download.docker.com/linux/ubuntu/gpg

  tasks:
    - name: adding docker gpg key
      apt_key:
        url: "{{ apt_gpg_key }}"
        state: present

    - name: add docker repository
      apt_repository:
        repo: "{{ apt_repo_data }}"
        state: present

    - name: installing docker-ce
      apt:
        name: docker-ce
        state: present
        update_cache: yes
    - name: install python-pip
      apt:
        name: python-pip
        state: present
    - name: install docker-py
      pip:
        name: "{{ item }}"
        state: present

      with_items:
        - docker-py

Docker 需要 64 位版本的操作系统和 Linux 内核版本大于或等于 3.10。 Docker 运行时也适用于 Windows 和 macOS。 对于本章的目的,我们将使用基于 Linux 的容器。 因此运行时可以在 Windows 上,但在其中运行的容器将是基于 Linux 的。 这些是可用于使用的标准 OWASP ZAP 容器。

OWASP ZAP Docker 容器设置

我们将在这里使用的两个新模块来处理 Docker 容器是 docker_imagedocker_container

这些模块要求您使用 2.1 及更高版本的 Ansible。现在是检查您的 Ansible 版本的好时机,可以使用 —version 标志。

如果您需要使用 pip 获取最新稳定版本,请运行以下命令:

pip install ansible --upgrade 

由于需要从互联网下载约 1GB 的数据,以下操作可能需要一些时间才能完成:

- name: setting up owasp zap container
  hosts: zap
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  become: yes
  vars:
    remote_user_name: ubuntu
    owasp_zap_image_name: owasp/zap2docker-weekly

  tasks:
    - name: pulling {{ owasp_zap_image_name }} container
      docker_image:
        name: "{{ owasp_zap_image_name }}"

    - name: running owasp zap container
      docker_container:
        name: owasp-zap
        image: "{{ owasp_zap_image_name }}"
        interactive: yes
        state: started
        user: zap
        command: zap.sh -daemon -host 0.0.0.0 -port 8090 -config api.disablekey=true -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true
        ports:
          - "8090:8090"
</span>

在以下配置中,我们说 api.disablekey=true,这意味着我们不使用任何 API 密钥。 这可以通过给定特定的 API 密钥来覆盖。 api.addrs.addr.name=.*api.addrs.addr.regex=true 将允许所有 IP 地址连接到 ZAP API。 有关 ZAP API 密钥设置的更多信息,请参阅 github.com/zaproxy/zaproxy/wiki/FAQapikey

您可以通过导航到 http://ZAPSERVERIPADDRESS:8090 来访问 ZAP API 界面:

OWASP ZAP API Web UI

用于处理容器的专用工具 - Ansible Container

目前,我们正在使用 Docker 模块执行容器操作。新工具 ansible-container 提供了一个 Ansible 中心化的工作流程,用于构建、运行、测试和部署容器。

这使我们能够使用现有的播放构建、推送和运行容器。Dockerfiles 就像编写 shell 脚本一样,因此,ansible-container 将允许我们将这些 Dockerfiles 编码化,并使用现有的播放构建它们,而不是编写复杂的脚本。

ansible-container 支持各种编排工具,如 Kubernetes 和 OpenShift。它还可以用于将构建的映像推送到私有注册表,如 Google Container Registry 和 Docker Hub。

docs.ansible.com/ansible-container/了解更多关于ansible-container的信息。

配置 ZAP 基线扫描

ZAP 基线扫描是在 ZAP Docker 镜像中可用的脚本。

更多关于 OWASP ZAP 基线扫描的详细信息可以在github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan找到。

此脚本的功能如下:

  • 对指定目标运行 ZAP 蜘蛛一分钟,然后执行被动扫描

  • 默认情况下,将所有警报报告为警告

  • 此脚本旨在在 CI/CD 环境中运行,甚至针对生产站点也是理想的。

在设置和运行 ZAP 基线扫描之前,我们希望运行一个简单易受攻击的应用程序,以便所有使用 ZAP 的扫描和测试都针对该应用程序运行,而不是针对真实世界的应用程序运行扫描,这是未经许可的。

运行一个易受攻击的应用容器

我们将使用Damn Vulnerable Web ServicesDVWS)应用程序(更多信息,请访问github.com/snoopysecurity/dvws)。它是一个带有多个易受攻击的 Web 服务组件的不安全 Web 应用程序,可用于学习真实世界的 Web 服务漏洞。

以下播放将设置运行 DVWS 应用程序的 Docker 容器:

- name: setting up DVWS container
  hosts: dvws
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  become: yes
  vars:
    remote_user_name: ubuntu
    dvws_image_name: cyrivs89/web-dvws

  tasks:
    - name: pulling {{ dvws_image_name }} container
      docker_image:
        name: "{{ dvws_image_name }}"

    - name: running dvws container
      docker_container:
        name: dvws
        image: "{{ dvws_image_name }}"
        interactive: yes
        state: started
        ports:
          - "80:80"

一旦播放成功执行,我们可以导航到 http://DVWSSERVERIP

DVWS 应用首页

现在,我们已经准备好对 DVWS 应用程序执行我们的 OWASP ZAP 基线扫描,通过运行基线扫描播放。

运行 OWASP ZAP 基线扫描

以下播放会针对给定的网站 URL 运行 Docker 基线扫描。它还将基线扫描的输出存储在主机系统中,以 HTML、Markdown 和 XML 格式进行存储:

- name: Running OWASP ZAP Baseline Scan
  hosts: zap
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  become: yes
  vars:
    remote_user_name: ubuntu
    owasp_zap_image_name: owasp/zap2docker-weekly
    website_url: {{ website_url }}
    reports_location: /zapdata/
    scan_name: owasp-zap-base-line-scan-dvws

  tasks:
    - name: adding write permissions to reports directory
      file:
        path: "{{ reports_location }}"
        state: directory
        owner: root
        group: root
        recurse: yes
        mode: 0770

    - name: running owasp zap baseline scan container against "{{ website_url }}"
      docker_container:
        name: "{{ scan_name }}"
        image: "{{ owasp_zap_image_name }}"
        interactive: yes
        auto_remove: yes
        state: started
        volumes: "{{ reports_location }}:/zap/wrk:rw"
        command: "zap-baseline.py -t {{ website_url }} -r {{ scan_name }}_report.html"

    - name: getting raw output of the scan
      command: "docker logs -f {{ scan_name }}"
      register: scan_output

    - debug:
        msg: "{{ scan_output }}"

让我们探索前面播放的参数:

  • website_url 是要执行基线扫描的域名(或)URL,我们可以通过 --extra-vars "website_url: http://192.168.33.111"ansible-playbook 命令传递这个参数

  • reports_location 是 ZAP 主机的路径,报告存储在其中。

下面的截图是来自 OWASP ZAP 的扫描报告输出:

OWASP ZAP 基线扫描 HTML 报告

要生成 Markdown 和 XML 格式的报告,请分别添加-w report.md-x report.xml到命令。

针对 Web 应用程序和网站进行安全测试

到目前为止,我们已经看到了如何使用 OWASP ZAP 容器运行基线扫描。现在我们将看到如何对 Web 应用程序执行主动扫描。主动扫描可能导致应用程序中的漏洞被利用。此外,这种类型的扫描需要额外的配置,包括身份验证和敏感功能。

对 DVWS 运行 ZAP 全面扫描

下面的 playbook 将针对 DVWS 应用程序运行全面扫描。现在我们可以看到 playbook 看起来几乎相似,只是发送给命令的标志不同:

- name: Running OWASP ZAP Full Scan
  hosts: zap
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  become: yes
  vars:
    remote_user_name: ubuntu
    owasp_zap_image_name: owasp/zap2docker-weekly
    website_url: {{ website_url }}
    reports_location: /zapdata/
    scan_name: owasp-zap-full-scan-dvws

  tasks:
    - name: adding write permissions to reports directory
      file:

        path: "{{ reports_location }}"
        state: directory
        owner: root
        group: root
        recurse: yes
        mode: 0777

    - name: running owasp zap full scan container against "{{ website_url }}"
      docker_container:
        name: "{{ scan_name }}"
        image: "{{ owasp_zap_image_name }}"
        interactive: yes
        auto_remove: yes
        state: started
        volumes: "{{ reports_location }}:/zap/wrk:rw"
        command: "zap-full-scan.py -t {{ website_url }} -r {{ scan_name }}_report.html"

    - name: getting raw output of the scan
      raw: "docker logs -f {{ scan_name }}"
      register: scan_output

    - debug:
        msg: "{{ scan_output }}"

OWASP ZAP 全面扫描检查了许多漏洞,其中包括 OWASP TOP 10(有关更多信息,请访问www.owasp.org/index.php/Category:OWASP_Top_Ten_Project)和许多其他漏洞。这可能对应用程序造成干扰,并向应用程序发送主动请求。它可能会基于应用程序中存在的漏洞对功能造成损害:

DVWS 应用程序的 OWASP ZAP 全面扫描报告

上面的截图是 OWASP ZAP 针对 DVWS 应用程序的全面扫描报告。我们可以清楚地看到基线扫描和全面扫描之间的差异,这是基于漏洞数量、不同类型的漏洞和风险评级。

测试 Web API

与 ZAP 基线扫描类似,ZAP 背后的可爱人士们提供了一个脚本作为他们的实时和每周 Docker 镜像的一部分。我们可以使用它来对由 OpenAPI 规范或简单对象访问协议SOAP)定义的 API 端点运行扫描。

脚本可以理解 API 规范并导入所有定义。基于此,它对找到的所有 URL 运行主动扫描:

- name: Running OWASP ZAP API Scan
  hosts: zap
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  become: yes
  vars:
    remote_user_name: ubuntu
    owasp_zap_image_name: owasp/zap2docker-weekly
    website_url: {{ website_url }}
    reports_location: /zapdata/
    scan_name: owasp-zap-api-scan-dvws
    api_type: openapi
>
  tasks:
    - name: adding write permissions to reports directory
      file:
        path: "{{ reports_location }}"
        state: directory
        owner: root
        group: root
        recurse: yes
        mode: 0777

    - name: running owasp zap api scan container against "{{ website_url }}"
      docker_container:
        name: "{{ scan_name }}"
        image: "{{ owasp_zap_image_name }}"
        interactive: yes
        auto_remove: yes
        state: started
        volumes: "{{ reports_location }}:/zap/wrk:rw"
        command: "zap-api-scan.py -t {{ website_url }} -f {{ api_type }} -r {{ scan_name }}_report.html"

    - name: getting raw output of the scan
      raw: "docker logs -f {{ scan_name }}"
      register: scan_output

    - debug:
        msg: "{{ scan_output }}"

使用 ZAP 和 Jenkins 进行持续扫描工作流

Jenkins 是一个开源自动化服务器。它在 CI/CD 流水线中被广泛使用。这些流水线通常指一系列基于触发器发生的自动化步骤,例如提交代码到版本控制软件或创建新版本。

我们已经看到了 ZAP 基线扫描作为 Mozilla 发布周期的一部分的示例。我们可以将 ZAP 与 Jenkins 集成。虽然我们可以有许多方式来实现这一点,但一组有用的步骤将是以下内容:

  1. 基于触发器,一个新的 ZAP 实例已经准备好进行扫描

  2. ZAP 实例针对自动部署的应用程序运行

  3. 扫描结果以某种格式捕获和存储

  4. 如果我们选择,结果也可以在诸如 Atlassian Jira 的缺陷跟踪系统中创建票证

为此,我们将首先设置我们的流水线基础设施:

  1. 使用 playbook 设置 Jenkins

  2. 添加官方 OWASP ZAP Jenkins 插件

  3. 使用另一个 playbook 触发工作流程

官方 OWASP ZAP Jenkins 插件可以在 wiki.jenkins.io/display/JENKINS/zap+plugin 找到。

设置 Jenkins

在服务器上设置 Jenkins 用作 OWASP ZAP 的 CI/CD 平台。 这将返回 Jenkins 管理员密码,一旦完成,我们就可以安装 Ansible 插件:

- name: installing jenkins in ubuntu 16.04
  hosts: jenkins
  remote_user: {{ remote_user_name }}
  gather_facts: False
  become: yes
  vars:
    remote_user_name: ubuntu

  tasks:
    - name: adding jenkins gpg key
      apt_key:
        url: 'https://pkg.jenkins.io/debian/jenkins-ci.org.key'
        state: present

    - name: jeknins repository to system
      apt_repository:
        repo: 'deb http://pkg.jenkins.io/debian-stable binary/'
        state: present
    - name: installing jenkins
      apt:
        name: jenkins
        state: present
        update_cache: yes

    - name: adding jenkins to startup
      service:
        name: jenkins
        state: started
        enabled: yes

    - name: printing jenkins default administration password
      command: cat "/var/lib/jenkins/secrets/initialAdminPassword"
      register: jenkins_default_admin_password

    - debug: 
        msg: "{{ jenkins_default_admin_password.stdout }}"

然后,我们可以将 playbook 添加到项目中。 当 Jenkins 构建中发生新的触发时,playbook 将开始扫描网站以执行基线扫描:

一旦 playbooks 触发,它将针对 URL 执行 playbooks 并返回 ZAP 基线扫描输出:

设置 OWASP ZAP Jenkins 插件

OWASP ZAP 与 Jenkins 配合工作是一个相当常见的设置。我们已经知道如何设置 Jenkins。我们可以使用我们的 playbook 安装官方 ZAP Jenkins 插件。

一旦 playbook 准备就绪,需要进行一些手动配置。 我们在我们的 playbook 安装了 Jenkins 并重新启动服务器后开始,以便插件可用于我们的构建作业。

让我们创建一个新的构建作业,并将其命名为 ZAP-Jenkins,如下面的屏幕截图所示:

对我们来说,这将是一个自由风格的项目。 现在我们将向其中添加 ZAP 的魔力:

我们正在按照 Jenkins 页面上官方插件的说明进行操作: wiki.jenkins.io/display/JENKINS/zap+plugin

需要一些组装

指定接口的 IP 地址和 ZAP 应监听的端口号。 通常,此端口为 8080,但由于 Jenkins 正在监听该端口,我们选择 8090

对于 JDK,我们选择唯一可用的选项,即从作业继承:

对于安装方法,我们选择已经安装在 /usr/share/owasp-zap 上的 ZAP。 我们将此值添加到 /etc/environment 中的 ZAPROXY_HOME 环境变量中。

这样做,我们确保环境变量值在系统重新启动时也能存活:

我们为超时设置了相当小的值,以确保万一出现问题,我们不必等待太久才能看到构建失败或 ZAP 无响应。

我们还指定了一个命令行选项,告诉 Jenkins ZAP 的安装目录是什么。

您可能需要单击“高级”按钮才能查看这些选项。

我们指定了 ZAP 主目录的路径:

然后我们配置从哪里加载 ZAP 会话:

这里显示了上下文名称、范围和排除项:

这是要测试的 URL 的起始点。我们计划执行的测试类型是爬虫扫描,默认为主动扫描:

最后,我们指定将生成的报告的文件名。我们添加BUILD_ID变量以确保我们无需担心覆盖报告。

触发构建(ZAP 扫描)

作业配置完成后,我们就可以触发构建了。当然,您也可以手动点击立即构建然后开始。

但我们将配置构建作业以远程触发,并同时传递必要的目标信息。

在常规下勾选此项目是参数化的:

在其中,我们添加一个带有默认值的TARGET参数。

在构建触发器下,我们指定一个身份验证令牌,以便在远程触发构建时作为参数传递:

请尽量确保此令牌足够长且随机,并且不是我们用作示例的简单单词。

在 Linux/macOS 中生成足够随机的字符串的一个好方法是使用 OpenSSL 命令。对于hex输出(20是输出的长度),使用**openssl rand -hex 20**。对于base64输出(24是输出的长度),使用**openssl rand -base64 24**

在此时,我们所要做的就是注意已登录用户的 API 令牌(从http://JENKINS-URL/user/admin/configure):

单击“显示 API 令牌”将显示令牌:

我们现在可以使用命令行工具,比如curl,来查看是否正常工作。

链接的格式是curl "http://username:API-TOKEN@JENKINS-URL/job/ZAP-Jenkins/buildWithParameters?TARGET=http://demo.testfire.net&token=ansible2security"

这将触发构建,应用程序将被扫描以查找安全问题。

使用自动化进行的操作指南

要执行前述触发器,我们可以使用以下 Ansible playbook。这也可以在我们的 Ansible Tower 中使用来安排扫描。

以下操作指南可以使用 Ansible Vault 存储 API 令牌密钥,该功能用于以加密格式存储 playbooks 中的机密数据。我们将在第十一章中学习有关 Ansible Vault 用法的更多信息,Ansible 安全最佳实践、参考资料和进一步阅读

要创建 Ansible Vault 加密变量,请运行以下命令。当它提示输入密码时,给出一个密码以加密此变量,执行 playbook 时需要。

echo 'YOURTOKENGOESHERE' | ansible-vault encrypt_string --stdin-name 'jenkins_api_token'

执行后,它会返回加密变量,我们可以直接在 playbook 中使用它作为变量:

- name: jenkins build job trigger
  hosts: localhost
  connection: local
  vars:
    jenkins_username: username
    jenkins_api_token: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          36636563313932313366313030623232623338333638363465343339636362353534363536366161
          3062666536613764396439326534663237653438616335640a613564643366623462666361633763
          31326161303666653366343931366265333238383937656435663061363665643431336638353436
          3532646434376533390a646332646639653161343165363832616233333232323130623034313032
          66643537336634633263346363313437666262323064386539616333646132353336
    jenkins_host: 192.168.11.111
    jenkins_target_url: 'http://demo.testfire.net'
    jenkins_token: ansible2security
>
  tasks:
    - name: trigger jenkins build
      uri:
        url: "http://{{ jenkins_username }}:{{ jenkins_api_token }}@{{ jenkins_host }}/job/ZAP-Jenkins/buildWithParameters?TARGET={{ jenkins_target_url }}&token={{ jenkins_token }}"
        method: GET
      register: results
    - debug:
        msg: "{{ results.stdout }}"

在执行 playbook 时执行 ansible-vault 解密,playbook 执行命令如下:

$ ansible-playbook --ask-vault-pass main.yml

ZAP Docker 和 Jenkins

Mozilla 的一群人撰写了一篇关于如何配置 ZAP Docker 与 Jenkins 的出色博客系列。与其重复他们的内容,我们觉得把你指向该系列的第一篇文章更有意义。

欲了解更多信息,请查看有趣的博客 Docker 化,OWASP-ZAP 安全扫描,在 Jenkins 中,第一部分,链接在:blog.mozilla.org/webqa/2016/05/11/docker-owasp-zap-part-one/

摘要

OWASP ZAP 是任何安全团队工具库中的绝佳选择。它在我们如何使用以及如何将其融入我们的设置中提供了完全的灵活性。通过将 ZAP 与 Jenkins 结合使用,我们可以快速建立一个体面的、适合生产的持续扫描工作流,并围绕它对我们的流程进行调整。Ansible 允许我们使用 playbooks 安装和配置所有这些优秀的工具。这很棒,因为这主要是一次性的努力,然后我们就可以开始看到 ZAP 的结果和报告。

现在我们正在自动化安全工具的过程中,接下来我们将看到最流行的漏洞评估工具 Nessus,以及我们如何为软件和网络的漏洞评估构建类似的工作流程。

使用 Nessus 进行漏洞扫描

漏洞扫描是安全团队在其计算机上进行的最为了解的定期活动之一。对于定期对计算机、网络、操作系统软件和应用软件进行漏洞扫描,都有充分记录的策略和最佳实践:

  • 基本网络扫描

  • 凭证补丁审核

  • 将系统信息与已知漏洞相关联

对于网络系统,这种类型的扫描通常是从具有适当权限的连接主机执行的,以便扫描安全问题。

最流行的漏洞扫描工具之一是 Nessus。Nessus 最初是一个网络漏洞扫描工具,但现在还包括以下功能:

  • 端口扫描

  • 网络漏洞扫描

  • Web 应用程序特定扫描

  • 基于主机的漏洞扫描

Nessus 简介

Nessus 拥有的漏洞数据库是其主要优势。虽然我们知道了理解哪个服务正在运行以及正在运行该服务的软件版本的技术,但回答“此服务是否有已知漏洞”这个问题是重要的。除了定期更新的漏洞数据库外,Nessus 还具有有关应用程序中发现的默认凭据、默认路径和位置的信息。所有这些都在易于使用的 CLI 或基于 Web 的工具中进行了优化。

在深入研究我们将如何设置 Nessus 来执行对基础架构进行漏洞扫描和网络扫描之前,让我们看看为什么我们必须设置它以及它将给我们带来什么回报。

在本章中,我们将专注于使用 Nessus 进行漏洞扫描。我们将尝试执行所需的标准活动,并查看使用 Ansible 自动化这些活动需要哪些步骤:

  1. 使用 playbook 安装 Nessus。

  2. 配置 Nessus。

  3. 运行扫描。

  4. 使用 AutoNessus 运行扫描。

  5. 安装 Nessus REST API Python 客户端。

  6. 使用 API 下载报告。

为漏洞评估安装 Nessus

首先,获取从 www.tenable.com/products/nessus/select-your-operating-system 下载 Nessus 的 URL,然后选择 Ubuntu 操作系统,然后对要设置 Nessus 的服务器运行以下 playbook 角色:

- name: installing nessus server
  hosts: nessus
  remote_user: "{{ remote_user_name }}"
  gather_facts: no
  vars:
    remote_user_name: ubuntu
    nessus_download_url: "http://downloads.nessus.org/nessus3dl.php?file=Nessus-6.11.2-ubuntu1110_amd64.deb&licence_accept=yes&t=84ed6ee87f926f3d17a218b2e52b61f0"

  tasks:
    - name: install python 2
      raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)

    - name: downloading the package and installing
      apt:
        deb: "{{ nessus_download_url }}"

    - name: start the nessus daemon
      service:
        name: "nessusd"
        enabled: yes
        state: started

配置 Nessus 进行漏洞扫描

执行以下步骤配置 Nessus 进行漏洞扫描:

  1. 我们必须导航至 https://NESSUSSERVERIP:8834 以确认并启动服务:

  1. 如我们所见,它返回一个 SSL 错误,我们需要接受 SSL 错误并确认安全异常,并继续安装:

  1. 单击确认安全异常并继续执行安装步骤:

  1. 点击继续并提供用户详细信息,该用户具有完整的管理员访问权限:

  1. 最后,我们必须提供注册码(激活码),这可以从注册页面获取:www.tenable.com/products/nessus-home

  1. 现在,它将安装所需的插件。安装需要一段时间,一旦完成,我们就可以登录使用应用程序:

  1. 现在,我们已成功设置了 Nessus 漏洞扫描器:

对网络执行扫描

现在,是时候使用 Nessus 执行一些漏洞扫描了。

基本网络扫描

Nessus 有各种各样的扫描,其中一些是免费的,一些只在付费版本中才可用。因此,我们也可以根据需要定制扫描。

下面是当前可用模板的列表:

  1. 我们可以从基本网络扫描开始,以查看网络中发生了什么。此扫描将为给定的主机执行基本的全系统扫描:

  1. 正如您在前面的截图中所看到的,我们必须提到扫描名称和目标。目标只是我们想要的主机。

目标可以以不同格式给出,例如192.168.33.1表示单个主机,192.168.33.1-10表示主机范围,我们还可以从计算机上载入目标文件。

选择 New Scan / Basic Network Scan 以使用 Nessus 进行分析:

  1. 我们也可以定制扫描类型。例如,我们可以执行常用端口扫描,该扫描将扫描已知端口,如果需要,我们还可以执行完整端口扫描:

  1. 然后,类似地,我们可以指定执行不同类型的 Web 应用程序扫描,如前所述:

  1. 报告也可以根据要求使用可用选项进行定制:

  1. 在扫描关键基础设施时,前述选项非常重要。这些选项旨在确保我们不会在目标网络中产生大量流量和网络带宽。Nessus 允许我们根据使用情况和需求进行定制:

  1. 前面的截图表示我们是否已经为任何服务拥有现有凭据,以及如果需要扫描,我们可以在此处提及它们。 Nessus 在扫描时将使用这些凭据进行身份验证,这样可以获得更好的结果。 Nessus 支持多种类型的身份验证服务!

  2. 如果需要,可以安排扫描,或者根据需要提供。 我们可以点击“启动”按钮(播放图标)以使用给定的配置参数开始扫描:

图片

  1. 扫描结果可以通过基于主机、漏洞、严重程度等的仪表板进行查看:

图片

  1. 上述截图显示了 Nessus 将如何生成现有漏洞的详细结果,包括样本概念证明POC)或命令输出。 它还提供了修复、漏洞和参考的详细摘要。

使用 AutoNessus 运行扫描

使用 AutoNessus 脚本,我们可以执行以下操作:

  • 列出扫描

  • 列出扫描策略

  • 对扫描执行操作,如启动、停止、暂停和恢复

AutoNessus 的最佳部分在于,由于这是一个命令行工具,因此可以轻松地成为定期任务和其他自动化工作流的一部分。

github.com/redteamsecurity/AutoNessus下载 AutoNessus。

设置 AutoNessus

以下代码是用于设置 AutoNessus 并配置其使用凭据的 Ansible playbook 片段。 此 playbook 将允许在路径中设置autoNessus工具,并且我们可以将其用作简单的系统工具:

- name: installing python-pip
  apt:
    name: python-pip
    update_cache: yes
    state: present

- name: install python requests
  pip:
    name: requests

- name: setting up autonessus
  get_url:
    url: "https://github.com/redteamsecurity/AutoNessus/raw/master/autoNessus.py"
    dest: /usr/bin/autoNessus
    mode: 0755

- name: updating the credentials
  replace:
    path: /usr/bin/autoNessus
    regexp: "{{ item.src }}"
    replace: "{{ item.dst }}"
    backup: yes
  no_log: True

  with_items:
    - { src: "token = ''", dst: "token = '{{ nessus_user_token }}'" }
    - { src: "url = 'https://localhost:8834'", dst: "url = '{{ nessus_url }}'" } 
    - { src: "username = 'xxxxx'", dst: "username = '{{ nessus_user_name }}'" }
    - { src: "password = 'xxxxx'", dst: "password = '{{ nessus_user_password }}'" }

no_log: True将在 Ansible 输出的日志控制台中对输出进行审查。 当我们在 playbooks 中使用密码和密钥时,这将非常有用。

使用 AutoNessus 运行扫描

以下的 playbook 代码片段可用于按需执行扫描以及定期执行的扫描。 这也可以在 Ansible Tower、Jenkins 或 Rundeck 中使用。

在使用 AutoNessus 进行自动化扫描之前,我们必须在 Nessus 门户中创建所需的自定义扫描,并且我们可以使用这些自动化 playbook 来执行任务。

列出当前可用的扫描和 ID

以下代码片段将返回当前可用的扫描并返回带有信息的 ID:

- name: list current scans and IDs using autoNessus
  command: "autoNessus -l"
  register: list_scans_output

- debug:
    msg: "{{ list_scans_output.stdout_lines }}"

图片

Ansible 输出返回可用扫描和 ID 信息的列表

使用扫描 ID 启动指定的扫描

以下代码片段将基于scan_id启动指定的扫描并返回状态信息:

- name: starting nessus scan "{{ scan_id }}" using autoNessus
  command: "autoNessus -sS {{ scan_id }}"
  register: start_scan_output

- debug:
    msg: "{{ start_scan_output.stdout_lines }}"

图片

启动后,Ansible 输出返回扫描状态

同样,我们可以执行暂停、恢复、停止、列出策略等操作。 使用 AutoNessus 程序,这些 playbook 是可用的。 这可以通过改进 Nessus API 脚本来改进。

存储结果

我们还可以获取与漏洞相关的详细信息、解决方案和风险信息:

图片

整个报告可以导出为多种格式,如 HTML、CSV 和 Nessus。 这有助于提供更详细的漏洞结构,带有风险评级的解决方案以及其他参考资料:

根据受众可以定制输出报告,如果发送给技术团队,我们可以列出所有漏洞和补救措施。例如,如果管理层想要报告,我们可以只得到问题的执行摘要。

报告也可以通过 Nessus 配置中的通知选项通过电子邮件发送。

以下截图是最近基本网络扫描的导出 HTML 格式的详细报告。这可以用来分析和修复基于主机的漏洞:

我们可以看到之前按主机分类的漏洞。我们可以在以下截图中详细查看每个漏洞:

安装 Nessus REST API Python 客户端

官方 API 文档可以通过连接到您的 Nessus 服务器下的 8834/nessus6-api.html 获取。

要使用 Nessus REST API 执行任何操作,我们必须从门户获取 API 密钥。这可以在用户设置中找到。请务必保存这些密钥:

使用 Nessus REST API 下载报告

以下 playbook 将使用 Nessus REST API 执行对给定 scan_id 报告的导出请求。它将使用一个简单的 playbook 自动化整个过程。这将返回报告的 HTML 输出:

- name: working with nessus rest api
  connection: local
  hosts: localhost
  gather_facts: no
  vars:
    scan_id: 17
    nessus_access_key: 620fe4ffaed47e9fe429ed749207967ecd7a77471105d8
    nessus_secret_key: 295414e22dc9a56abc7a89dab713487bd397cf860751a2
    nessus_url: https://192.168.33.109:8834
    nessus_report_format: html

  tasks:
    - name: export the report for given scan "{{ scan_id }}"
      uri:
        url: "{{ nessus_url }}/scans/{{ scan_id }}/export"
        method: POST
        validate_certs: no
        headers:
            X-ApiKeys: "accessKey={{ nessus_access_key }}; secretKey={{ nessus_secret_key }}"
        body: "format={{ nessus_report_format }}&chapters=vuln_by_host;remediations"
      register: export_request

    - debug:
        msg: "File id is {{ export_request.json.file }} and scan id is {{ scan_id }}"

    - name: check the report status for "{{ export_request.json.file }}"
      uri:
        url: "{{ nessus_url }}/scans/{{ scan_id }}/export/{{ export_request.json.file }}/status"
        method: GET
        validate_certs: no
        headers:
            X-ApiKeys: "accessKey={{ nessus_access_key }}; secretKey={{ nessus_secret_key }}"
      register: report_status

    - debug:
        msg: "Report status is {{ report_status.json.status }}"

    - name: downloading the report locally
      uri:
        url: "{{ nessus_url }}/scans/{{ scan_id }}/export/{{ export_request.json.file }}/download"
        method: GET
        validate_certs: no
        headers:
          X-ApiKeys: "accessKey={{ nessus_access_key }}; secretKey={{ nessus_secret_key }}"
        return_content: yes
        dest: "./{{ scan_id }}_{{ export_request.json.file }}.{{ nessus_report_format }}"
      register: report_output

    - debug:
      msg: "Report can be found at ./{{ scan_id }}_{{ export_request.json.file }}.{{ nessus_report_format }}"

在 Nessus REST API  cloud.tenable.com/api#/overview 阅读更多。

使用 Nessus REST API 进行自动报告生成的 Ansible playbook:

使用 Nessus REST API 进行自动报告生成和导出的 Ansible playbook

Nessus 配置

Nessus 允许我们创建具有基于角色的认证的不同用户来执行扫描和以不同访问级别审查:

下图显示了如何创建一个具有执行 Nessus 活动权限的新用户的过程:

摘要

安全团队和 IT 团队依赖工具进行漏洞扫描、管理、补救和持续安全流程。由于 Nessus 是最流行和最有用的工具之一,它是作者尝试自动化的自动选择。

在本章中,我们看了漏洞扫描的主要活动,如能够安装和部署工具,启动扫描和下载报告。

在下一章中,我们将深入探讨系统安全和加固。我们将研究各种开放的安全倡议和基准项目,如 STIG、OpenSCAP 和互联网安全中心CIS)。我们将学习如何将它们与我们的 playbooks 和自动化工具,如 Tower 和 Jenkins,集成起来。这一章关于漏洞扫描,以及下一章关于网络和应用程序安全加固,为探索更多关于安全自动化和保持系统安全和加固的思路奠定了坚实基础。

应用程序和网络的安全加固

安全加固是任何注重安全的努力中最明显的任务。通过保护系统、应用程序和网络,可以实现多个安全目标,如下所述:

  • 确保应用程序和网络没有受到威胁(有时)

  • 使威胁难以长期隐藏

  • 默认情况下进行安全加固,确保网络的一部分遭受威胁时不会进一步传播和蔓延

Ansible 在围绕安全自动化方面的思考方式非常适合用于自动化安全加固。在本章中,我们将介绍可以用于构建 playbook 的安全基准和框架,这些 playbook 将允许我们做以下事情:

  • 确保我们的主镜像安全,以便应用程序和系统一旦成为网络的一部分,它们就提供了合适的安全性

  • 执行审计过程,以便我们可以周期性地验证和测量应用程序、系统和网络是否符合组织所需的安全策略

这绝不是一个新的想法。在这个领域已经进行了大量工作。我们将看一些项目,如 dev-sec.io (dev-sec.io/), 它们使我们可以简单地开始对应用程序和网络进行安全加固。

本章将涵盖的主题如下:

  • 使用 CIS、STIG 和 NIST 等基准进行安全加固

  • 使用 Ansible 自动化进行网络设备的安全审计检查

  • 使用 Ansible 自动化进行应用程序的安全审计检查

  • 使用 Ansible 进行自动打补丁的方法

使用 CIS、STIG 和 NIST 等基准进行安全加固

基准为任何人提供了获得其个人安全努力保证的好方法。这些基准由全球安全专家创建,或由安全成熟的政府部门如 NIST 领导,涵盖了各种系统、配置、软件等。

安全加固主要归结为以下几点:

  1. 达成一致,确定最小配置集合何时符合安全配置的定义。通常将其定义为加固基准或框架。

  2. 对受到此类配置影响的系统的所有方面进行更改。

  3. 定期测量应用程序和系统是否仍与配置一致,或是否存在任何偏差。

  4. 如果发现任何偏差,立即采取纠正措施修复它。

  5. 如果没有发现任何偏差,记录下来。

  6. 由于软件始终在升级,跟踪最新的配置指南和基准非常重要。

我们讨论的三个重要的基准/框架是:

  • CIS 基准

  • STIG 指南

  • NIST 的国家检查清单计划(NCP)

这些 CIS 基准通常以 PDF 文档的形式表达,任何想了解他们的系统与 CIS 专家对其安全性的看法相比有多安全的人都可以获得。

CIS 是一个非营利性组织,为互联网安全制定了非营利性标准,并被认可为全球标准和最佳实践,用于保护 IT 系统和数据免受攻击。CIS 基准是唯一由政府、企业、行业和学术界开发并接受的基于共识的最佳实践安全配置指南。更多信息,请访问 www.cisecurity.org/cis-benchmarks

STIG 与美国政府部门DISA的信息系统配置相关。

STIGs 包含了技术指导,用于锁定可能易受恶意计算机攻击影响的信息系统/软件。更多信息,请访问 iase.disa.mil/stigs/Pages/index.aspx

NIST 维护一个以符合安全内容自动化协议SCAP)的文件形式表达的检查表程序。软件工具可以读取这些文件以自动化配置更改和审计运行配置。

SCAP 使得验证过的安全工具可以使用 SCAP 表达的 NCP 检查表来自动执行配置检查。更多信息请访问 www.nist.gov/programs-projects/national-checklist-program

使用 Ansible 剧本对基线进行操作系统加固

到目前为止,我们已经创建了多个剧本来执行某些操作。现在,我们将看到如何使用社区提供的现有剧本(Ansible Galaxy)。

Hardening Framework 是德国电信的一个项目,用于管理成千上万台服务器的安全性、合规性和维护。该项目的目标是创建一个通用的层,以便轻松地加固操作系统和服务。

如果你的组织使用 chef 或 puppet 工具作为配置管理工具,那么这些概念完全相同。你可以在 dev-sec.io 找到相关的菜谱和详细信息。

以下的剧本提供了多种安全配置、标准以及保护操作系统免受不同攻击和安全漏洞的方法。

它将执行的一些任务包括以下内容:

  • 配置软件包管理,例如,只允许签名软件包

  • 删除已知问题的软件包

  • 配置 pampam_limits 模块

  • Shadow 密码套件配置

  • 配置系统路径权限

  • 通过软限制禁用核心转储

  • 限制 root 登录到系统控制台

  • 设置 SUIDs

  • 通过 sysctl 配置内核参数

从 galaxy 下载和执行 Ansible 剧本就像下面这样简单:

$ ansible-galaxy install dev-sec.os-hardening
- hosts: localhost
  become: yes
  roles:
    - dev-sec.os-hardening

在执行中的 dev-sec.os-hardening 剧本

前面的 playbook 将检测操作系统,并根据不同的指南执行加固步骤。可以通过更新默认变量值来配置此内容。有关 playbook 的更多详细信息,请参阅 github.com/dev-sec/ansible-os-hardening

用于 Linux 主机的自动化安全加固的 STIGs Ansible 角色

OpenStack 有一个名为 ansible-hardening 的令人敬畏的项目(github.com/openstack/ansible-hardening),它根据 STIGs 标准应用安全配置更改。有关 Unix/Linux 操作系统的 STIGs 基准的更多详细信息,请访问 iase.disa.mil/stigs/os/unix-linux/Pages/index.aspx

它为以下领域执行安全强化:

  • accounts: 用户帐户安全控制

  • aide: 高级入侵检测环境

  • auditd: 审计守护程序

  • auth: 认证

  • file_perms: 文件系统权限

  • graphical: 图形化登录安全控制

  • kernel: 内核参数

  • lsm: Linux 安全模块

  • misc: 杂项安全控制

  • packages: 软件包管理器

  • sshd: SSH 守护程序

ansible-hardening playbook 支持多个 Linux 操作系统

  • CentOS 7

  • Debian jessie

  • Fedora 26

  • openSUSE Leap 42.2 和 42.3

  • Red Hat Enterprise Linux 7

  • SUSE Linux Enterprise 12(实验性)

  • Ubuntu 16.04

有关项目和文档的更多详细信息,请参阅 docs.openstack.org/ansible-hardening/latest

使用 ansible-galaxy 从 GitHub 存储库本身下载角色,如下所示:

$ ansible-galaxy install git+https://github.com/openstack/ansible-hardening

playbook 如下所示。与以前的 playbook 类似,可以通过更改默认变量值来配置它所需的内容:

- name: STIGs ansible-hardening for automated security hardening
  hosts: servers
  become: yes
  remote_user: "{{ remote_user_name }}"
  vars:
    remote_user_name: vagrant
    security_ntp_servers:
      - time.nist.gov
      - time.google.com

  roles:
    - ansible-hardening

一个在 CentOS-7 上执行的 Ansible-hardening playbook 用于 STIGs checklist

前面的 playbook 在 CentOS-7 服务器上执行,用于执行 STIG checklist。

使用 Ansible Tower 进行 OpenSCAP 的持续安全扫描和报告

OpenSCAP 是一组安全工具、策略和标准,通过遵循 SCAP 对系统执行安全合规性检查。SCAP 是由 NIST 维护的美国标准。

SCAP 扫描器应用程序读取 SCAP 安全策略,并检查系统是否符合该策略。它逐个检查策略中定义的所有规则,并报告每个规则是否得到满足。如果所有检查都通过,则系统符合安全策略。

OpenSCAP 按照以下步骤对系统进行扫描:

  • 安装 SCAP Workbench 或 OpenSCAP Base(有关更多信息,请访问 www.open-scap.org

  • 选择一个策略

  • 调整您的设置

  • 评估系统

以下 playbook 将安装 openscap-scannerscap-security-guide 软件来执行检查。然后,它将根据给定的配置文件和策略使用 oscap 工具执行扫描。

正如您所见,变量 oscap_profile 是从可用配置文件列表中选择配置文件,oscap_policy 是选择用于扫描系统的特定策略:

- hosts: all
  become: yes
  vars:
    oscap_profile: xccdf_org.ssgproject.content_profile_pci-dss
    oscap_policy: ssg-rhel7-ds

  tasks:
  - name: install openscap scanner
    package:
      name: "{{ item }}"
      state: latest
    with_items:
    - openscap-scanner
    - scap-security-guide

  - block:
    - name: run openscap
      command: >
        oscap xccdf eval
        --profile {{ oscap_profile }}
        --results-arf /tmp/oscap-arf.xml
        --report /tmp/oscap-report.html
        --fetch-remote-resources
        /usr/share/xml/scap/ssg/content/{{ oscap_policy }}.xml

    always:
    - name: download report
      fetch:
        src: /tmp/oscap-report.html
        dest: ./{{ inventory_hostname }}.html
        flat: yes

medium.com/@jackprice/ansible-openscap-for-compliance-automation-14200fe70663查看 playbooks 参考。

现在,我们可以使用此 playbook 使用 Ansible Tower 进行持续自动化检查:

  1. 首先,我们需要在 Ansible Tower 服务器上创建一个目录,以便使用 awx 用户权限存储此 playbook 以添加自定义 playbook。

  2. 在 Ansible Tower 中创建一个新项目,执行 OpenSCAP 设置并针对检查进行扫描:

  1. 然后,我们必须创建一个新作业来执行此 playbook。在这里,我们可以包含主机列表、登录凭据和执行所需的其他详细信息:

  1. 可以定期安排执行此审核。在这里,您可以看到我们每天都安排,这可以根据合规性频率进行修改(安全合规性要求经常执行这些类型的审核):

  1. 我们也可以根据需要随时启动此作业。playbook 的执行如下所示:

  1. playbook 的输出将生成 OpenSCAP 报告,并将其获取到 Ansible Tower。我们可以在 /tmp/ 位置访问此 playbook。此外,如果需要,我们还可以将此报告发送到其他集中式报告服务器。

  1. 我们还可以根据 playbook 执行结果设置通知。通过这样做,我们可以将此通知发送到相应的渠道,如电子邮件、slack 和消息。

CIS 基准

CIS 为不同类型的操作系统、软件和服务制定了基准。以下是一些高级分类:

  • 桌面和网络浏览器

  • 移动设备

  • 网络设备

  • 安全指标

  • 服务器 – 操作系统

  • 服务器 – 其他

  • 虚拟化平台、云和其他

了解有关 CIS 基准的更多信息,请访问www.cisecurity.org

Ubuntu CIS 基准(服务器级别)

CIS 基准 Ubuntu 提供了为运行在 x86 和 x64 平台上的 Ubuntu Linux 系统建立安全配置姿态的指导方针。此基准适用于系统和应用程序管理员、安全专家、审计员、帮助台和计划开发、部署、评估或保护包含 Linux 平台的解决方案的平台部署人员。

这是 CIS Ubuntu 16.04 LTS 基准的六个高级域的概述:

  • 初始设置:

    • 文件系统配置

    • 配置软件更新

    • 文件系统完整性检查

    • 安全引导设置

    • 附加进程强化

    • 强制访问控制

    • 警告横幅

  • 服务:

    • Inted 服务

    • 专用服务

    • 服务客户端

  • 网络配置:

    • 网络参数(仅主机)

    • 网络参数(主机和路由器)

    • IPv6

    • TCP 包装器

    • 不常见的网络协议

  • 日志和审计:

    • 配置系统会计(auditd

    • 配置日志记录

  • 访问、身份验证和授权:

    • 配置 cron

    • SSH 服务器配置

    • 配置 PAM

    • 用户帐户和环境

  • 系统维护:

    • 系统文件权限

    • 用户和组设置

这是分别用于 14.04 LTS 和 16.04 LTS 的 Ansible Playbooks:

$ git clone https://github.com/oguya/cis-ubuntu-14-ansible.git
$ cd cis-ubuntu-14-ansible

然后,更新变量和清单,并使用以下命令执行 playbook。除非我们想要根据组织自定义基准,否则大多数情况下不需要变量:

$ ansible-playbook -i inventory cis.yml

CIS Ubuntu 基准 Ansible playbook 执行

前述 playbook 将针对 Ubuntu 服务器执行 CIS 安全基准,并执行 CIS 指南中列出的所有检查。

AWS 基准(云提供商级别)

AWS CIS 基准提供了针对 AWS 子集的安全选项配置的指导方针,重点是基础、可测试和与架构无关的设置。适用于计划在 AWS 中开发、部署、评估或保护解决方案的系统和应用程序管理员、安全专家、审计员、帮助台、平台部署和/或 DevOps 人员。

这是 AWS CIS 基准的高级域:

  • 身份和访问管理

  • 日志记录

  • 监控

  • 网络

  • 额外

目前,有一个名为prowler的工具(github.com/Alfresco/prowler),它基于 AWS-CLI 命令用于 AWS 帐户安全评估和加固。

这些工具遵循 CIS Amazon Web Services Foundations Benchmark 1.1 的准则

在运行 playbook 之前,我们必须提供 AWS API 密钥以执行安全审核。这可以使用 AWS 服务中的 IAM 角色创建。如果您已经有一个具有所需权限的现有帐户,则可以跳过这些步骤:

  1. 在您的 AWS 帐户中创建一个具有编程访问权限的新用户:

  1. 为用户从 IAM 控制台中的现有策略应用 SecurityAudit 策略:

  1. 然后,按照步骤创建新用户。确保安全保存访问密钥 ID 和秘密访问密钥以供以后使用:

  1. 这是使用 prowler 工具设置和执行检查的简单 playbook。从前面的步骤提供访问密钥和秘密密钥。

  2. 以下 playbook 假定您已经在本地系统中安装了pythonpip

        - name: AWS CIS Benchmarks playbook
          hosts: localhost
          become: yes
          vars:
            aws_access_key: XXXXXXXX
            aws_secret_key: XXXXXXXX

          tasks:
            - name: installing aws cli and ansi2html
              pip:
                name: "{{ item }}"

            with_items:
              - awscli
              - ansi2html

            - name: downloading and setting up prowler
              get_url:
                url:         https://raw.githubusercontent.com/Alfresco/prowler/master
        /prowler
                dest: /usr/bin/prowler
                mode: 0755

            - name: running prowler full scan
              shell: "prowler | ansi2html -la > ./aws-cis-report-{{         ansible_date_time.epoch }}.html"
              environment:
                AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
                AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"

            - name: AWS CIS Benchmarks report downloaded
              debug:
                msg: "Report can be found at ./aws-cis-report-{{         ansible_date_time.epoch }}.html"
  1. 该 playbook 将使用 prowler 工具触发 AWS CIS 基准的设置和安全审计扫描:

  1. Prowler 生成的 HTML 报告如下,报告可以按需下载为不同格式,并且扫描检查可以根据需要配置:

有关该工具的更多参考资料可以在github.com/Alfresco/prowler找到。

Lynis - 用于 Unix/Linux 系统的开源安全审计工具

Lynis 是一个开源安全审计工具。被系统管理员、安全专业人员和审计员使用,评估他们的 Linux 和基于 Unix 的系统的安全防御。它在主机上运行,因此执行的安全扫描比漏洞扫描器更加广泛。

支持的操作系统:Lynis 几乎可以在所有基于 Unix 的系统和版本上运行,包括以下系统:

  • AIX

  • FreeBSD

  • HP-UX

  • Linux

  • macOS

  • NetBSD

  • OpenBSD

  • Solaris 和其他系统

cisofy.com/lynis所述:

"甚至可以在像树莓派或 QNAP 存储设备等系统上运行。"

该 playbook 如下所示:

- name: Lynis security audit playbook
  hosts: lynis
  remote_user: ubuntu
  become: yes
  vars:
    # refer to https://packages.cisofy.com/community
    code_name: xenial

  tasks:
    - name: adding lynis repo key
      apt_key:
        keyserver: keyserver.ubuntu.com
        id: C80E383C3DE9F082E01391A0366C67DE91CA5D5F
        state: present

    - name: installing apt-transport-https
      apt:
        name: apt-transport-https
        state: present

    - name: adding repo
      apt_repository:
        repo: "deb https://packages.cisofy.com/community/lynis/deb/ {{ code_name }} main"
        state: present
        filename: "cisofy-lynis"

    - name: installing lynis
      apt:
        name: lynis
        update_cache: yes
        state: present

    - name: audit scan the system
      shell: lynis audit system > /tmp/lynis-output.log

    - name: downloading report locally
      fetch:
        src: /tmp/lynis-output.log
        dest: ./{{ inventory_hostname }}-lynis-report-{{ ansible_date_time.date }}.log
        flat: yes

    - name: report location
      debug:
        msg: "Report can be found at ./{{ inventory_hostname }}-lynis-report-{{ ansible_date_time.date }}.log"

上述 playbook 将设置 Lynis,对其进行系统审计扫描,最后在本地获取报告:

Lynis 系统审计扫描 playbook 正在执行

以下屏幕截图是最近审计扫描的报告:

Lynis 系统审计扫描报告

可以通过 Ansible Tower 和其他自动化工具运行此项,以执行使用 Lynis 进行审计扫描的系统的周期性检查。

Lynis 命令和高级选项

Lynis 具有多个选项和命令,可用于执行不同的选项。例如,我们可以使用audit dockerfile <filename>来执行 Dockerfiles 的分析,使用--pentest选项来执行与渗透测试相关的扫描。

使用 Ansible playbooks 进行 Windows 服务器审计

大多数企业使用 Windows 通过 Active Directory 类型的功能集中管理其政策和更新,这也是保护组织并检查安全问题的非常关键的资产。我们知道 Ansible 支持使用 WinRM 执行配置更改的 Windows 操作系统。让我们看一些示例,通过 Ansible playbooks 为您的 Windows 服务器添加安全性。

Windows 安全更新 playbook

下面的 playbook 是从 Ansible 文档中简单引用的参考,网址为 docs.ansible.com/ansible/devel/windows_usage.html#installing-updates

- name: Windows Security Updates
  hosts: winblows

  tasks:
    - name: install all critical and security updates
      win_updates:
        category_names:
        - CriticalUpdates
        - SecurityUpdates
        state: installed
      register: update_result

    - name: reboot host if required
      win_reboot:
      when: update_result.reboot_required

图片

Windows 更新 playbook 正在运行

前面的 playbook 将自动执行临界严重性的 Windows 安全更新,并在需要时重新启动计算机以应用更新后的更改。

Windows 工作站和服务器审计

下面的 Ansible playbook 是基于 github.com/alanrenouf/Windows-Workstation-and-Server-Audit, 创建的,它将对系统进行审计并生成详细的 HTML 报告。这是一个我们可以使用 PowerShell 脚本执行审计的示例。可以通过添加更多检查和其他安全审计脚本来扩展此功能。

Playbook 如下所示:

- name: Windows Audit Playbook
  hosts: winblows

  tasks:
    - name: download audit script
      win_get_url:
        url: https://raw.githubusercontent.com/alanrenouf/Windows-Workstation-and-Server-Audit/master/Audit.ps1
        dest: C:\Audit.ps1

    - name: running windows audit script
      win_shell: C:\Audit.ps1
      args:
        chdir: C:\

图片

Windows 审计 playbook 正在运

一旦 playbook 执行完成,我们可以在 HTML 格式的输出报告中看到有关运行服务、安全补丁、事件、日志记录和其他配置详细信息。

图片

使用 Ansible 自动化进行网络设备的安全审计检查

我们已经看到 Ansible 很适合与各种工具一起使用,我们可以利用它来进行网络设备的安全审计检查。

Nmap 扫描和 NSE

网络映射器Nmap)是一个免费的开源软件,用于进行网络发现、扫描、审计等。它具有各种功能,如操作系统检测、系统指纹识别、防火墙检测等。Nmap 脚本引擎Nmap NSE)提供了高级功能,如扫描特定的漏洞和攻击。我们还可以编写和扩展自己的自定义脚本来使用 Nmap。Nmap 是渗透测试人员(安全测试人员)和网络安全团队的瑞士军刀。

nmap.org 上了解更多关于 Nmap 的信息。Ansible 还有一个模块可以使用 Nmap 执行清单 github.com/ansible/ansible/pull/32857/files

下面的 playbook 将在必要时安装 Nmap 并使用指定的标志执行基本网络端口扫描:

- name: Basic NMAP Scan Playbook
  hosts: localhost
  gather_facts: false
  vars:
    top_ports: 1000
    network_hosts:
      - 192.168.1.1
      - scanme.nmap.org
      - 127.0.0.1
      - 192.168.11.0/24

  tasks:
    - name: check if nmap installed and install
      apt:
        name: nmap
        update_cache: yes
        state: present
      become: yes

    - name: top ports scan
      shell: "nmap --top-ports {{ top_ports }} -Pn -oA nmap-scan-%Y-%m-%d {{ network_hosts|join(' ') }}"
  • {{ network_hosts|join(' ') }} 是一个名为 filter arguments 的 Jinja2 功能,用于通过空格分隔解析给定的 network_hosts

  • network_hosts 变量保存要使用 Nmap 扫描的 IP 列表、网络范围(CIDR)、主机等。

  • top_ports 是一个范围从 065535 的数字。Nmap 默认选择常见的顶级端口

  • -Pn 指定如果 ping(ICMP)不起作用,则扫描主机

  • -oA 将输出格式设置为所有格式,其中包括 gnmap(可 greppable 格式)、Nmap 和 XML

  • 更多关于 nmap 的选项和文档信息可以在nmap.org/book/man.html找到。

Nmap 基本端口扫描 playbook 执行

运行基本 Nmap 扫描的 playbook 的输出为:

图:playbook 以三种不同的格式进行扫描输出

执行 playbook 后,生成了 Nmap 支持的三种格式的报告:

图:nmap 格式的 playbook 扫描输出

通过查看.nmap文件的输出,我们可以轻松地看到 Nmap 扫描发现了什么。

Nmap NSE 扫描 playbook

以下 playbook 将使用 Nmap 脚本执行对常用 Web 应用和服务器使用的目录进行枚举,并使用 Nmap 脚本查找 HTTP 服务器支持的选项。

更多关于 Nmap NSE 的信息可以在nmap.org/book/nse.html找到。

以下的 playbook 将对scanme.nmap.org的端口80443进行http-enumhttp-methods扫描:

- name: Advanced NMAP Scan using NSE
  hosts: localhost
  vars:
    ports:
      - 80
      - 443
    scan_host: scanme.nmap.org 

  tasks:
    - name: Running Nmap NSE scan
      shell: "nmap -Pn -p {{ ports|join(',') }} --script {{ item }} -oA nmap-{{ item }}-results-%Y-%m-%d {{ scan_host }}"

      with_items:
        - http-methods
        - http-enum

以下的 playbook 将使用 Ansible playbook 执行 Nmap NSE 脚本进行 HTTP 枚举和方法检查:

执行 Nmap NSE playbook

运行简单的 NSE 脚本时,playbook 的输出如下所示:

Nmap NSE 扫描的.nmap 格式输出

http-enum脚本在检测到网络端口上有 Web 服务器时会运行额外的测试。在前面的截图中,我们可以看到脚本发现了两个文件夹,并且还枚举了所有支持的 HTTP 方法。

使用 Scout2 进行 AWS 安全审计

Scout2 是一款开源的 AWS 安全审计工具,它使用 AWS Python API 来评估 AWS 环境的安全状况。扫描输出将以 JSON 格式存储,并且 Scout2 的最终结果将以简单的 HTML 网站的形式呈现,其中包含了关于 AWS 云安全状况的详细信息。它根据现有的规则集和测试用例执行扫描和审核,并且可以根据我们的自定义脚本和场景进行扩展。

更多关于该工具的详细信息可以在github.com/nccgroup/Scout2找到。此工具需要 AWS IAM 凭证来执行扫描;请参考github.com/nccgroup/AWS-recipes/blob/master/IAM-Policies/Scout2-Default.json以创建用户策略。

使用以下 playbook 安装 AWS Scout2 非常简单:

- name: AWS Security Audit using Scout2
  hosts: localhost
  become: yes

  tasks:
    - name: installing python and pip
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes

      with_items:
        - python
        - python-pip

    - name: install aws scout2
      pip:
        name: awsscout2

配置了多个规则来进行审核,以下代码片段是 IAM 密码策略规则的示例:

# https://raw.githubusercontent.com/nccgroup/Scout2/master/tests/data/rule-configs/iam-password-policy.json
{
    "aws_account_id": "123456789012",
    "services": {
        "iam": {
            "password_policy": {
                "ExpirePasswords": false,
                "MinimumPasswordLength": "1",
                "PasswordReusePrevention": false,
                "RequireLowercaseCharacters": false,
                "RequireNumbers": false,
                "RequireSymbols": false,
                "RequireUppercaseCharacters": false
            }
        }
    }
}

以下的 playbook 会执行 AWS Scout2 扫描,并以 HTML 格式返回报告:

- name: AWS Security Audit using Scout2
  hosts: localhost
  vars:
    aws_access_key: XXXXXXXX
    aws_secret_key: XXXXXXXX

  tasks:
    - name: running scout2 scan
      # If you are performing from less memory system add --thread-config 1 to below command
      command: "Scout2"
      environment:
        AWS_ACCESS_KEY_ID: "{{ aws_access_key }}"
        AWS_SECRET_ACCESS_KEY: "{{ aws_secret_key }}"

    - name: AWS Scout2 report downloaded
      debug:
        msg: "Report can be found at ./report.html"

AWS Scout2 报告高级概览

上述屏幕截图是高级报告,详细报告如下:

AWS Scout2 报告 IAM 部分的详细结果

使用 Ansible 对应用程序进行自动化安全审计检查

现代应用程序很快就会变得非常复杂。拥有运行自动化执行安全任务的能力几乎是一个强制性要求。

我们可以进行的不同类型的应用程序安全扫描包括以下内容:

  1. 对源代码运行 CI/CD 扫描(例如,RIPS 和 brakeman)。

  2. 依赖项检查扫描器(例如,OWASP 依赖项检查器和 snyk.io (snyk.io/))。

  3. 一旦部署,然后运行 Web 应用程序扫描器(例如,Nikto、Arachni 和 w3af)。

  4. 针对特定框架的安全扫描器(例如,WPScan 和 Droopscan)以及许多其他。

源代码分析扫描器

这是在应用程序即将投入生产时最早和常见的减少安全风险的方式之一。源代码分析扫描器,也称为静态应用程序安全测试SAST),将通过分析应用程序的源代码来帮助发现安全问题。这种工具和测试方法允许开发人员在持续集成/持续交付CI/CD)的过程中反复自动地扫描其代码以查找安全漏洞。

我们可以引入这些工具的多个阶段来有效地识别安全漏洞,比如与 IDE 集成(诸如 Eclipse、Visual Studio Code 等代码编辑器)以及与 CI/CD 过程工具集成(Jenkins、Travis CI 等)。

源代码分析是一种白盒测试,它查看代码。这种测试方法可能无法发现 100% 的安全漏洞覆盖率,而且还需要手动测试。例如,要找到逻辑漏洞,需要某种用户交互,如动态功能。

在市场上有许多开源和商业工具可用于执行静态代码分析。此外,一些工具是针对您使用的技术和框架的。例如,如果您正在扫描 PHP 代码,则使用 RIPS (rips-scanner.sourceforge.net/);如果是 Ruby on Rails 代码,则使用 Brakeman (brakemanscanner.org/);如果是 Python,则使用 Bandit (wiki.openstack.org/wiki/Security/Projects/Bandit);依此类推。

更多参考,请访问 www.owasp.org/index.php/Source_Code_Analysis_Tools

Brakeman 扫描器 - Rails 安全扫描器

Brakeman 是一个开源工具,用于对 Ruby on Rails 应用程序进行静态安全分析。 这可以应用于开发和部署流程的任何阶段,包括分期、QA、生产等。

用于执行 Brakeman 对我们应用程序的简单 playbook 如下:

- name: Brakeman Scanning Playbook
  hosts: scanner
  remote_user: ubuntu
  become: yes
  gather_facts: false
  vars:
    repo_url: https://github.com/OWASP/railsgoat.git
    output_dir: /tmp/railsgoat/
    report_name: report.html

  tasks:
    - name: installing ruby and git
      apt:
        name: "{{ item }}"
        update_cache: yes
        state: present

      with_items:
        - ruby-full
        - git

    - name: installing brakeman gem
      gem:
        name: brakeman
        state: present

    - name: cloning the {{ repo_url }}
      git:
        repo: "{{ repo_url }}"
        dest: "{{ output_dir }}"

    - name: Brakeman scanning in action
      # Output available in text, html, tabs, json, markdown and csv formats
      command: "brakeman -p {{ output_dir }} -o {{ output_dir }}report.html"
      # Error handling for brakeman output
      failed_when: result.rc != 3
      register: result

    - name: Downloading the report
      fetch:
        src: "{{ output_dir }}/report.html"
        dest: "{{ report_name }}"
        flat: yes

    - debug:
        msg: "Report can be found at {{ report_name }}"

Brakeman Playbook 在 Rails goat 项目中的操作

Brakeman 报告的概述是:

Brakeman 报告的高级概述

这是 Brakeman 报告的详细情况:

这是一个包含代码和问题级别的详细报告。

有关 Brakeman 工具和选项的参考信息可在 brakemanscanner.org 找到。

依赖检查扫描器

大多数开发人员在开发应用程序时使用第三方库,使用开源插件和模块在其代码中非常常见。 许多开源项目可能容易受到已知攻击的影响,如跨站脚本和 SQL 注入。 如果开发人员不知道所使用库中存在的漏洞,那么他们的整个应用程序就会因为使用了糟糕的库而变得容易受到攻击。

因此,依赖性检查将允许我们通过扫描库来查找应用程序代码中存在的已知漏洞(OWASP A9)问题,并与 CVE 和 NIST 漏洞数据库进行比较。

市场上有多个项目可用于执行这些检查,其中一些包括以下内容:

  • OWASP Dependency-Check

  • Snyk.io (snyk.io/)

  • Retire.js

  • [:] SourceClear 以及许多其他

OWASP Dependency-Check

OWASP Dependency-Check 是一个开源工具,主要用于检查 Java 和 .NET 应用程序中已知的漏洞。 它还支持其他平台,如 Node.js 和 Python 作为实验分析器。 这也可能产生误报,并可以根据需要进行配置以调整扫描。

这个工具也可以以多种方式运行,比如 CLI、构建工具(Ant、Gradle、Maven 等)和 CI/CD(Jenkins)流程。

有关项目的更多详细信息,请访问 www.owasp.org/index.php/OWASP_Dependency_Check

以下代码片段用于在易受攻击的 Java 项目上设置和使用 OWASP Dependency-Check 工具进行扫描:

- name: OWASP Dependency Check Playbook
  hosts: scanner
  remote_user: ubuntu
  become: yes
  vars:
    repo_url: https://github.com/psiinon/bodgeit.git
    output_dir: /tmp/bodgeit/
    project_name: bodgeit
    report_name: report.html

  tasks:
    - name: installing pre requisuites
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes

      with_items:
        - git
        - unzip
        - mono-runtime
        - mono-devel
        - default-jre

    - name: downloading owasp dependency-check
      unarchive:
        src: http://dl.bintray.com/jeremy-long/owasp/dependency-check-3.0.2-release.zip
        dest: /usr/share/
        remote_src: yes

    - name: adding symlink to the system
      file:
        src: /usr/share/dependency-check/bin/dependency-check.sh
        dest: /usr/bin/dependency-check
        mode: 0755
        state: link

    - name: cloning the {{ repo_url }}
      git:
        repo: "{{ repo_url }}"
        dest: "{{ output_dir }}"

    - name: updating CVE database
      command: "dependency-check --updateonly"

    - name: OWASP dependency-check scanning in action
      # Output available in XML, HTML, CSV, JSON, VULN, ALL formats
      command: "dependency-check --project {{ project_name }} --scan {{ output_dir }} -o {{ output_dir }}{{ project_name }}-report.html"

    - name: Downloading the report
      fetch:
        src: "{{ output_dir }}{{ project_name }}-report.html"
        dest: "{{ report_name }}"
        flat: yes

    - debug:
        msg: "Report can be found at {{ report_name }}" 

使用 Ansible playbook 对 Bodgeit 项目执行 OWASP Dependency-Check 扫描

高级 OWASP Dependency-Check 报告:

OWASP Dependency-Check 工具的高级报告

这是一个包含漏洞、修复措施和参考资料的详细报告:

包含漏洞、修复措施和参考资料的详细报告

高级报告格式如下:

  • 依赖项:扫描的依赖项的文件名

  • CPE:发现的任何通用平台枚举标识符

  • GAV: Maven 组、Artifact 和版本(GAV)

  • 最高严重性:任何相关 CVE 的最高严重性

  • CVE 数量:相关 CVE 的数量

  • CPE 确信度:Dependency-check 确定已正确识别 CPE 的可信度排名

  • 证据数量:从用于识别 CPE 的依赖项中提取的数据量

可以在jeremylong.github.io/DependencyCheck找到更详细的文档。

运行 Web 应用程序安全扫描器

这是应用程序上线到 QA、阶段(或)生产环境的阶段。然后,我们希望像攻击者一样执行安全扫描(黑盒视图)。在此阶段,应用程序将应用所有动态功能和服务器配置。

这些扫描器的结果告诉我们服务器配置得有多好以及在将复制品发布到生产环境之前是否存在任何其他应用程序安全问题。

在这个阶段,大多数扫描器只能在某个特定水平上工作。我们需要通过人脑进行一些手动测试,以发现逻辑漏洞和其他安全漏洞,这些漏洞无法被安全扫描器和工具检测到。

正如我们在其他部分中所看到的,市场上有许多工具可以代替您执行这些工作,无论是开源还是商业。其中一些包括以下内容:

  • Nikto

  • Arachni

  • w3af

  • Acunetix 和许多其他工具

Nikto - web 服务器扫描器

Nikto 是一个用 Perl 编写的开源 Web 服务器评估工具,用于执行安全配置检查和 Web 服务器和应用程序扫描,使用其要扫描的条目清单。

Nikto 进行的一些检查包括以下内容:

  • 服务器和软件配置错误

  • 默认文件和程序

  • 不安全的文件和程序

  • 过时的服务器和程序

Nikto 设置和执行 Ansible playbook 如下所示:

- name: Nikto Playbook
  hosts: scanner
  remote_user: ubuntu
  become: yes
  vars:
    domain_name: idontexistdomainnamewebsite.com # Add the domain to scan
    report_name: report.html

  tasks:
    - name: installing pre requisuites
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes

      with_items:
        - git
        - perl
        - libnet-ssleay-perl
        - openssl
        - libauthen-pam-perl
        - libio-pty-perl
        - libmd-dev

    - name: downloading nikto
      git:
        repo: https://github.com/sullo/nikto.git
        dest: /usr/share/nikto/

    - name: Nikto scanning in action
      # Output available in csv, html, msf+, nbe, txt, xml formats
      command: "/usr/share/nikto/program/nikto.pl -h {{ domain_name }} -o /tmp/{{ domain_name }}-report.html"

    - name: downloading the report
      fetch:
        src: "/tmp/{{ domain_name }}-report.html"
        dest: "{{ report_name }}"
        flat: yes

    - debug:
        msg: "Report can be found at {{ report_name }}"

Nikto Playbook 实例

用于下载、安装和运行带有报告输出的 Nikto 的 Playbook 如下:

Nikto HTML 扫描报告

了解更多关于 Nikto 选项和文档的信息:cirt.net/Nikto2.

特定框架的安全扫描器

这种类型的检查和扫描是针对特定的框架、CMS 和平台进行的。它允许通过对多个安全测试案例和检查进行验证来获得更详细的结果。同样,在开源和商业世界中有多种工具和扫描器可用。

一些示例包括以下内容:

WordPress 漏洞扫描器 – WPScan

WPScan 是一个用 Ruby 编写的黑盒 WordPress 漏洞扫描器,用于针对 WordPress CMS 使用 WPScan 漏洞数据库 (wpvulndb.com) 进行安全扫描和漏洞检查。

它执行的一些检查包括但不限于以下内容:

  • WordPress 核心

  • WordPress 插件和主题

  • 已知的旧软件漏洞

  • 用户名,附件枚举

  • 暴力破解攻击

  • 安全配置错误等等

以下 Playbook 将根据给定的域执行 WPScan,并生成带有问题列表和参考信息的扫描报告。

根据需要更新 Playbook 中的domain_nameoutput_dir值。此外,以下 Playbook 假定您已在系统中安装了 Docker:

- name: WPScan Playbook
  hosts: localhost
  vars:
    domain_name: www.idontexistdomainnamewebsite.com # Specify the domain to scan
    wpscan_container: wpscanteam/wpscan
    scan_name: wpscan
    output_dir: /tmp # Specify the output directory to store results

  tasks:
    # This playbook assumes docker already installed
    - name: Downloading {{ wpscan_container }} docker container
      docker_image:
        name: "{{ wpscan_container }}"

    - name: creating output report file
      file:
        path: "{{output_dir }}/{{ domain_name }}.txt"
        state: touch

    - name: Scanning {{ domain_name }} website using WPScan
      docker_container:
        name: "{{ scan_name }}"
        image: "{{ wpscan_container }}"
        interactive: yes
        auto_remove: yes
        state: started
        volumes: "/tmp/{{ domain_name }}.txt:/wpscan/data/output.txt"
        command: ["--update", "--follow-redirection", "--url", "{{ domain_name }}", "--log", "/wpscan/data/output.txt"]

    - name: WPScan report downloaded
      debug:
        msg: "The report can be found at /tmp/{{ domain_name }}.txt"

WPScan Ansible playbook 执行

下载、执行和存储 WPScan 扫描结果的 Playbook 输出:

带有问题详情和参考信息的 WPScan 输出报告

这些扫描可以集成到我们的 CI/CD 管道中,并在部署完成后执行以验证安全检查和配置检查。此外,根据需要可以根据 WPScan 定制此扫描;有关更多参考,请参阅 WPScan 文档 github.com/wpscanteam/wpscan

使用 Ansible 的自动修补方法

补丁和更新是每个必须管理生产系统的人都必须处理的任务。我们将看到的两种方法如下:

  • 滚动更新

  • 蓝绿部署

滚动更新

想象一下我们在负载均衡器后面有五台 web 服务器。我们想要做的是对我们的 Web 应用进行零停机升级。使用 Ansible 中提供的某些关键字,我们可以实现这一点。

在我们的示例中,我们希望实现以下目标:

  • 告诉负载均衡器 web 服务器节点已经宕机

  • 将该节点上的 web 服务器关闭

  • 将更新后的应用程序文件复制到该节点

  • 在该节点上启动 web 服务器

我们首先要查看的关键字是serial。让我们从 Ansible 文档中看一个例子:

- name: test play
  hosts: webservers
  serial: 1

该示例来自 docs.ansible.com/ansible/latest/playbooks_delegation.html#rolling-update-batch-size

这确保了 Playbook 的执行是串行而不是并行进行的。因此,我们先前列出的步骤可以逐个节点完成。负载均衡器将流量分发到正在运行的节点上的网站,并且我们实现了滚动更新。

除了给 serial 一个数字之外,我们还可以使用百分比。因此,示例变为以下形式:

- name: test play
  hosts: webservers
  serial: "20%"

示例来自 docs.ansible.com/ansible/latest/playbooks_delegation.html#rolling-update-batch-size

我们可以选择为 serial 提供百分比值或数字值。在这种情况下,play 将针对 1 个节点运行,然后是剩余节点的 20%,最后是所有剩余节点。

# The batch sizes can be a list as well
- name: test play
  hosts: webservers
  serial:
    - "1"
    - "20%"
    - "100%"

示例来自 docs.ansible.com/ansible/latest/playbooks_delegation.html#rolling-update-batch-size

这种更新方式的一个很好的示例在下面的链接中给出

第 47 集 - 使用 Ansible 进行零停机部署sysadmincasts.com/episodes/47-zero-downtime-deployments-with-ansible-part-4-4

蓝绿部署

蓝绿的概念归功于马丁·福勒。一个很好的参考是这篇文章 martinfowler.com/bliki/BlueGreenDeployment.html。其想法是将我们当前的生产工作负载视为蓝色。现在我们想要做的是升级应用程序。因此,在相同的负载均衡器后面启动蓝色的副本。基础设施的副本具有更新的应用程序。

一旦它启动并运行,负载均衡器配置将从当前的蓝色切换到指向绿色。蓝色保持运行,以防有任何操作问题。一旦我们对进展满意,就可以关闭旧主机。下面的 playbook 以非常简单的方式演示了这一点:

  • 第一个 playbook 启动三个主机。两个运行 nginx 的 Web 服务器在负载均衡器后面

  • 第二个 playbook 将当前正在运行的内容(蓝色)切换为绿色

蓝绿部署设置 playbook

以下 playbook 将设置三个节点,包括负载均衡器和两个 Web 服务器节点。请参阅 www.upcloud.com/support/haproxy-load-balancer-ubuntu 创建一个 playbook。

下面的代码片段是 inventory 文件:

[proxyserver]
proxy ansible_host=192.168.100.100 ansible_user=ubuntu ansible_password=passwordgoeshere

[blue]
blueserver ansible_host=192.168.100.10 ansible_user=ubuntu ansible_password=passwordgoeshere

[green]
greenserver ansible_host=192.168.100.20 ansible_user=ubuntu ansible_password=passwordgoeshere

[webservers:children]
blue
green

[prod:children]
webservers
proxyserver

然后,main.yml playbook 文件如下所示,描述了在哪些节点上执行哪些角色和流程:

- name: running common role
  hosts: prod
  gather_facts: false
  become: yes
  serial: 100%
  roles:
    - common

- name: running haproxy role
  hosts: proxyserver
  become: yes 
  roles:
    - haproxy

- name: running webserver role
  hosts: webservers
  become: yes 
  serial: 100% 
  roles:
    - nginx

- name: updating blue code
  hosts: blue
  become: yes 
  roles:
    - bluecode

- name: updating green code
  hosts: green
  become: yes 
  roles:
    - greencode

每个角色都有其自己的功能要执行;以下是在所有节点上执行的常见角色:

- name: installing python if not installed
  raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)

- name: updating and installing git, curl
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - git
    - curl

# Also we can include common any monitoring and security hardening tasks

然后,代理服务器角色如下所示,用于设置和配置 haproxy 服务器:

- name: adding haproxy repo
  apt_repository:
    repo: ppa:vbernat/haproxy-1.7

- name: updating and installing haproxy
  apt:
    name: haproxy
    state: present
    update_cache: yes

- name: updating the haproxy configuration
  template:
    src: haproxy.cfg.j2
    dest: /etc/haproxy/haproxy.cfg

- name: starting the haproxy service
  service:
    name: haproxy
    state: started
    enabled: yes

haproxy.cfg.j2 如下所示,其中包含执行设置所需的所有配置。根据我们想要添加(或)移除的配置,可以进行改进,如 SSL/TLS 证书和暴露 haproxy 统计信息等:

global
  log /dev/log local0
  log /dev/log local1 notice
  chroot /var/lib/haproxy
  stats socket /run/haproxy/admin.sock mode 660 level admin
  stats timeout 30s
  user haproxy
  group haproxy
  daemon

  # Default SSL material locations
  ca-base /etc/ssl/certs
  crt-base /etc/ssl/private

  # Default ciphers to use on SSL-enabled listening sockets.
  # For more information, see ciphers(1SSL). This list is from:
  # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
  # An alternative list with additional directives can be obtained from
  # https://mozilla.github.io/server-side-tls/ssl-config-generator/?server=haproxy
  ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS
  ssl-default-bind-options no-sslv3

defaults
  log global
  mode http
  option httplog
  option dontlognull
        timeout connect 5000
        timeout client 50000
        timeout server 50000
  errorfile 400 /etc/haproxy/errors/400.http
  errorfile 403 /etc/haproxy/errors/403.http
  errorfile 408 /etc/haproxy/errors/408.http
  errorfile 500 /etc/haproxy/errors/500.http
  errorfile 502 /etc/haproxy/errors/502.http
  errorfile 503 /etc/haproxy/errors/503.http
  errorfile 504 /etc/haproxy/errors/504.http

frontend http_front
   bind *:80
   stats uri /haproxy?stats
   default_backend http_back

backend http_back
   balance roundrobin
   server {{ hostvars.blueserver.ansible_host }} {{ hostvars.blueserver.ansible_host }}:80 check
   #server {{ hostvars.greenserver.ansible_host }} {{ hostvars.greenserver.ansible_host }}:80 check

下面的代码片段将服务器添加为负载均衡器的一部分,并在用户请求时提供服务。我们也可以添加多个服务器。haproxy还支持 L7 和 L4 负载平衡:

server {{ hostvars.blueserver.ansible_host }} {{ hostvars.blueserver.ansible_host }}:80 check

Web 服务器是非常简单的 nginx 服务器设置,用于安装并将服务添加到启动过程中:

- name: installing nginx
  apt:
    name: nginx
    state: present
    update_cache: yes

- name: starting the nginx service
  service:
    name: nginx
    state: started
    enabled: yes

最后,以下代码片段分别是bluegreen服务器的代码:

<html>
    <body bgcolor="blue">
       <h1 align="center">Welcome to Blue Deployment</h1>
    </body>
</html>
<html>
    <body bgcolor="green">
        <h1 align="center">Welcome to Green Deployment</h1>
    </body>
</html>

以下是整个设置的 playbook 执行的参考截图:

一旦 playbook 完成,我们就可以在负载均衡器 IP 地址上检查生产站点,查看蓝色部署:

BlueGreen 部署更新 playbook

现在,开发人员已经更新了代码(或者)服务器已经修补了一些安全漏洞。我们希望使用绿色部署部署生产站点的新版本。

playbook 看起来非常简单,如下所示,它将更新配置并重新加载 haproxy 服务以服务新的生产部署:

- name: Updating to GREEN deployment
  hosts: proxyserver
  become: yes 

  tasks:
    - name: updating proxy configuration
      template:
        src: haproxy.cfg.j2
        dest: /etc/haproxy/haproxy.cfg

    - name: updating the service
      service:
        name: haproxy
        state: reloaded

    - debug:
        msg: "GREEN deployment successful. Please check your server :)"

然后,我们可以再次检查我们的生产站点,通过导航到负载均衡器 IP 地址来查看更新的部署:

现在,我们可以看到我们的生产站点正在运行新的更新部署。HAProxy 中有多个高级选项可用于执行不同类型的更新,并且可以根据需要进行配置。

摘要

本章涉及了应用程序和网络安全的各种用例。通过将各种工具与 Ansible playbook 的强大功能相结合,我们在这个领域创建了强大的安全自动化工作流程。根据需求,您可以使用基准来启用安全默认值或定期检查合规性并满足审计要求。我们研究了允许我们对 AWS 云执行相同操作的工具。从应用程序安全扫描器到以安全配置驱动的软件更新和补丁方法,我们尝试涵盖一系列任务,这些任务通过 Ansible 自动化变得强大。

在下一章中,我们将专注于 IT 和运维中最激动人心的新兴领域之一,即容器。Docker 作为容器的代名词,已经成为开发人员、系统管理员广泛部署的技术,也是现代软件开发和部署流程的核心组成部分。让我们探索 Ansible 与 Docker 容器配合使用的秘密。

Docker 容器的持续安全扫描

Docker 容器是开发人员打包应用程序的新方法。容器最好的特性是它们包含了代码、运行时、系统库以及应用程序工作所需的所有设置。由于易于使用和部署,越来越多的应用程序正在以容器形式部署用于生产。

由于有这么多的活动部分,我们迫切需要有能力持续扫描 Docker 容器以寻找安全问题。在本章中,我们将看到各种做到这一点的方法。从使用 Ansible 调用的熟悉的 CIS 基准脚本开始,我们将转向 clair-scanner,这是一个用于扫描现有漏洞并与现有的 CI/CD 工作流程很好地集成的工具,如果需要的话。

在本章中,我们将详细探讨以下主题:

  • 理解持续安全的概念

  • 使用 Ansible 自动化 Docker 容器的漏洞评估

  • 使用 Ansible Tower 对 Docker 安全进行定期扫描

  • 使用 Ansible Tower 对操作系统和内核安全进行定期扫描

  • 使用 Ansible 进行文件完整性检查和主机级监控的定期扫描,以满足各种合规性要求

理解持续安全的概念

DevOps 中出现的一个关键方法是不可变基础设施的概念。这意味着每当需要进行运行时更改,无论是应用程序代码还是配置,都会重新构建和部署容器,并且会销毁现有的运行容器。

由于这样可以实现可预测性、弹性,并简化运行时的部署选择,因此毫无疑问,许多运维团队正在朝着这个方向发展。伴随而来的问题是这些容器应该何时进行安全和合规性测试。通过接受本章讨论的持续安全扫描和监控的流程,您可以自动化各种工作负载和工作流程。

使用 Ansible 自动化 Docker 容器的漏洞评估

容器无处不在。让我们看一些使用 Ansible 进行扫描和评估 Docker 容器和环境的技术和工具。

评估容器安全有许多不同的方法。在本章中,我们将看一些方法以及它们如何与 Ansible 结合使用:

工具 描述
Docker Bench 基于 CIS 进行检查的安全 Shell 脚本
Clair 基于 CVE 数据库进行漏洞分析的工具
Anchore 用于执行安全评估并做出运行时策略决策的工具
vuls 一种无需代理的漏洞扫描器,具有 CVE、OVAL 数据库
osquery 用于进行 OS 分析的 OS 仪表化框架,以执行 HIDS 类型的活动

Docker 安全检查

Docker 安全工作台是一个 shell 脚本,用于对 Docker 容器环境进行多项检查。它将根据 CIS 基准提供更详细的安全配置视图。由于它是基于符合 POSIX 2004 标准构建的,所以该脚本支持大多数 Unix 操作系统。

有关工具信息的更多详细信息,请访问github.com/docker/docker-bench-security

以下是此脚本将执行的检查的高级区域:

  • 主机

  • Docker 守护程序配置和文件

  • Docker 容器映像

  • Docker 运行时

  • Docker 安全操作

  • Docker 集群配置

以下 Playbook 将针对 Docker 环境执行 Docker 安全检查,并返回详细的报告:

- name: Docker bench security playbook
  hosts: docker
  remote_user: ubuntu
  become: yes

  tasks:
    - name: make sure git installed
      apt:
        name: git
        state: present

    - name: download the docker bench security
      git:
        repo: https://github.com/docker/docker-bench-security.git
        dest: /opt/docker-bench-security

    - name: running docker-bench-security scan
      command: docker-bench-security.sh -l /tmp/output.log
      args:
        chdir: /opt/docker-bench-security/

    - name: downloading report locally
      fetch:
        src: /tmp/output.log
        dest: "{{ playbook_dir }}/{{ inventory_hostname }}-docker-report-{{ ansible_date_time.date }}.log"
        flat: yes

    - name: report location
      debug:
        msg: "Report can be found at {{ playbook_dir }}/{{ inventory_hostname }}-docker-report-{{ ansible_date_time.date }}.log"</mark>

Docker 安全检查 Ansible Playbook 的执行:

图片

Docker 安全检查 Ansible Playbook 的执行

Playbook 的输出将下载并扫描基于 CIS 基准的容器,并将结果存储在log文件中,其输出可以在此处看到:

图片

详细的 Docker 安全检查分析报告

Clair

Clair 允许我们通过与现有漏洞数据库进行检查来对容器执行静态漏洞分析。它允许我们使用 Clair 数据库对我们的 Docker 容器映像执行漏洞分析检查。有关 Clair 的更多详细信息,请访问github.com/coreos/clair

设置 Clair 本身真的很困难,并且使用 Docker 映像的 API 进行扫描会使得情况更加复杂。这就是 clair-scanner 的用武之地,它使得通过 REST API 进行设置和执行扫描变得非常简单。

请在github.com/arminc/clair-scanner中阅读更多关于 clair-scanner 的信息。

Clair-scanner 可以根据某些事件触发对容器进行简单扫描,以检查现有的漏洞。此外,该报告可以转发给负责修复等工作的团队。

以下 Playbook 将设置所需的 Docker 容器和配置以执行 clair-scanning。它假设目标系统已安装了 Docker 和所需的库:

- name: Clair Scanner Server Setup
  hosts: docker
  remote_user: ubuntu
  become: yes

  tasks:
    - name: setting up clair-db
      docker_container:
        name: clair_db
        image: arminc/clair-db
        exposed_ports:
          - 5432

    - name: setting up clair-local-scan
      docker_container:
        name: clair
        image: arminc/clair-local-scan:v2.0.1
        ports:
          - "6060:6060"
        links:
          - "clair_db:postgres"

以下截图展示了使用 Ansible 设置 clair-scanner 与 Docker 容器的执行。

图片

使用 Ansible 设置 clair-scanner 与 Docker 容器

在执行 Playbook 后,下载和设置 CVE 数据库将需要一段时间。

以下 Playbook 将用于运行 clair-scanner,通过向服务器发出 API 请求对容器进行分析:

- name: Scanning containers using clair-scanner
  hosts: docker
  remote_user: ubuntu
  become: yes
  vars:
    image_to_scan: "debian:sid"   #container to scan for vulnerabilities
    clair_server: "http://192.168.1.10:6060"    #clair server api endpoint

  tasks:
    - name: downloading and setting up clair-scanner binary
      get_url:
        url: https://github.com/arminc/clair-scanner/releases/download/v6/clair-scanner_linux_amd64
        dest: /usr/local/bin/clair-scanner
        mode: 0755

    - name: scanning {{ image_to_scan }} container for vulnerabilities
      command: clair-scanner -r /tmp/{{ image_to_scan }}-scan-report.json -c {{ clair_server }} --ip 0.0.0.0 {{ image_to_scan }}
      register: scan_output
      ignore_errors: yes

    - name: downloading the report locally
      fetch:
        src: /tmp/{{ image_to_scan }}-scan-report.json
        dest: {{ playbook_dir }}/{{ image_to_scan }}-scan-report.json
        flat: yes

以下截图展示了针对请求的 Docker 映像执行 clair-scanner 的情况。正如您所看到的致命错误,所以当它发现 Docker 映像存在任何问题时,它会返回错误,我们可以使用ignore_errors来处理它。

Clair-scanner 执行过程

这是运行 clair-scanner 的 playbook 输出以及 JSON 格式的报告输出:

报告的输出包括漏洞 CVE 和严重程度

使用 Ansible Tower 进行定期扫描 Docker 安全性

持续安全性流程涉及计划、执行、测量和行动的循环:

来自维基共享的 Deming 循环

通过遵循标准的检查表和基准,并使用 Ansible 在容器上执行它们,我们可以检查安全问题并对其采取行动。Anchore 是一个用于容器的分析和检查平台。

Anchore - 开放式容器合规性平台

Anchore 是执行容器镜像分析、检查和认证的最流行的工具和服务之一。它提供多个服务和平台进行设置,最稳定和强大的方式是使用 Anchore Engine 设置本地服务,可以通过 REST API 访问。在以下文档中,我们将看到如何使用 Anchore Engine 设置服务以及如何使用这个 REST API 执行 Docker 容器的持续安全扫描和分析。

以下是 Anchore 可执行的高级操作:

  • 策略评估操作

  • 图像操作

  • 策略操作

  • 注册操作

  • 订阅操作

  • 系统操作

github.com/anchore/anchore-engine了解更多关于 Anchore 引擎服务的信息。

设置 Anchore 引擎服务

以下 playbook 将设置 Anchore 引擎服务,其中包含引擎容器以及用于存储数据库信息的 postgresadmin_password 变量是访问 Anchore REST API 的管理员用户密码:

- name: anchore server setup
  hosts: anchore
  become: yes
  vars:
    db_password: changeme
    admin_password: secretpassword

  tasks:
    - name: creating volumes
      file:
        path: "{{ item }}"
        recurse: yes
        state: directory

      with_items:
        - /root/aevolume/db
        - /root/aevolume/config

    - name: copying anchore-engine configuration
      template:
        src: config.yaml.j2
        dest: /root/aevolume/config/config.yaml

    - name: starting anchore-db container
      docker_container:
        name: anchore-db
        image: postgres:9
        volumes:
          - "/root/aevolume/db/:/var/lib/postgresql/data/pgdata/"
        env:
          POSTGRES_PASSWORD: "{{ db_password }}"
          PGDATA: "/var/lib/postgresql/data/pgdata/"

    - name: starting anchore-engine container
      docker_container:
        name: anchore-engine
        image: anchore/anchore-engine
        ports:
          - 8228:8228
          - 8338:8338
        volumes:
          - "/root/aevolume/config/config.yaml:/config/config.yaml:ro"
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
        links:
          - anchore-db:anchore-db

以下截图是执行 Anchore 引擎服务设置的 Ansible playbook 执行过程:

使用 Ansible playbook 设置 Anchore 引擎服务

Anchore CLI 扫描器

现在我们已经拥有了 Anchore 引擎服务的 REST API 访问详情,我们可以利用这一点在任何主机上执行容器镜像的扫描。以下步骤是配置 Ansible Tower 来执行持续的容器镜像漏洞扫描。

用于扫描容器镜像的 playbook 如下所示:

- name: anchore-cli scan
  hosts: anchore
  become: yes
  vars:
    scan_image_name: "docker.io/library/ubuntu:latest"
    anchore_vars:
      ANCHORE_CLI_URL: http://localhost:8228/v1
      ANCHORE_CLI_USER: admin
      ANCHORE_CLI_PASS: secretpassword

  tasks:
    - name: installing anchore-cli
      pip:
        name: "{{ item }}"

      with_items:
        - anchorecli
        - pyyaml

    - name: downloading image
      docker_image: 
        name: "{{ scan_image_name }}"

    - name: adding image for analysis
      command: "anchore-cli image add {{ scan_image_name }}"
      environment: "{{anchore_vars}}"

    - name: wait for analysis to compelte
      command: "anchore-cli image content {{ scan_image_name }} os"
      register: analysis
      until: analysis.rc != 1
      retries: 10
      delay: 30
      ignore_errors: yes
      environment: "{{anchore_vars}}"

    - name: vulnerabilities results
      command: "anchore-cli image vuln {{ scan_image_name }} os"
      register: vuln_output
      environment: "{{anchore_vars}}"

    - name: "vulnerabilities in {{ scan_image_name }}"
      debug:
        msg: "{{ vuln_output.stdout_lines }}"

可以根据需要自定义执行 anchore-cli 的选项,请参阅github.com/anchore/anchore-cli的文档。

现在,我们必须在 Ansible Tower 中创建新项目以添加 playbook。然后我们可以从版本控制中选择 playbook 源,或者提供详细信息:

我们也可以通过 Ansible Tower UI 传递变量。正如您所见,我们正在传递一些秘密,我们将看到如何利用 Ansible Vault 安全存储和使用它们:

我们还可以按需安排此 Playbook 每周或每月运行,根据需要进行设置。还请注意,这可以根据用例进行定制:

然后,我们还可以通过启动作业执行按需扫描。以下截图是关于 ubuntu:latest Docker 镜像漏洞的参考,其中包含 CVE 详细信息和易受攻击的软件包列表:

使用 Ansible Tower 定期扫描操作系统和内核安全

持续的安全扫描要求我们在类似 Ansible Tower 的软件中进行管理。虽然大多数讨论的工具都可用于扫描和维护安全基准,但我们应考虑事故响应和威胁检测工作流程的整个过程:

  1. 准备工作

  2. 检测和分析

  3. 遏制、根除和恢复

  4. 事后活动

设置所有这些扫描器是我们的准备工作。使用这些扫描器的输出使我们能够进行检测和分析。遏制和恢复都超出了这些工具的范围。对于恢复和事后活动的流程,您可能需要考虑可以销毁当前基础架构并按原样重新创建的 Playbook。

作为准备的一部分,熟悉以下术语可能很有用,因为您会在漏洞扫描器和漏洞管理工具的世界中反复看到它们的使用:

术语 全称(如果有) 术语描述
CVE 通用漏洞和暴露 这是一个网络安全漏洞标识符列表。通常使用 CVE ID。
OVAL 开放式漏洞和评估语言 用于发现和命名计算机系统中的漏洞和配置问题的语言。
CWE 通用弱点枚举 软件安全弱点的通用列表。
NVD 国家漏洞数据库 美国政府的漏洞管理数据库,以 XML 格式公开供公众使用。

Vuls - 漏洞扫描器

Vuls 是一个用 golang 编写的无代理扫描器。它支持各种不同的 Linux 操作系统。它执行完整的端到端安全系统管理任务,如扫描安全漏洞和安全软件更新。它根据 CVE 分数对系统进行所需的安全漏洞分析,通过 Slack 和电子邮件发送通知,并提供具有历史数据的简单 Web 报告。

github.com/future-architect/vuls 了解更多关于 vuls 的信息。

Vuls 设置 Playbook

以下 playbook 用于在 Ubuntu 16.04 系统上使用 Docker 容器设置vuls。 以下 playbook 假定您已经安装了 docker 和所需的软件包。

playbook 主要有两个角色,用于使用 Docker 容器设置vuls

  • vuls_containers_download

  • vuls_database_download

- name: setting up vuls using docker containers
  hosts: vuls
  become: yes

  roles:
    - vuls_containers_download
    - vuls_database_download

使用docker_image模块在本地拉取 Docker 容器:

- name: pulling containers locally
  docker_image:
    name: "{{ item }}"
    pull: yes

  with_items:
    - vuls/go-cve-dictionary
    - vuls/goval-dictionary
    - vuls/vuls

然后下载所需操作系统和分发版本的 CVE 和 OVAL 数据库:

- name: fetching NVD database locally
  docker_container:
    name: "cve-{{ item }}"
    image: vuls/go-cve-dictionary
    auto_remove: yes
    interactive: yes
    state: started
    command: fetchnvd -years "{{ item }}"
    volumes:
      - "{{ vuls_data_directory }}:/vuls"
      - "{{ vuls_data_directory }}/go-cve-dictionary-log:/var/log/vuls"
  with_sequence: start=2002 end="{{ nvd_database_years }}"

- name: fetching redhat oval data
  docker_container:
    name: "redhat-oval-{{ item }}"
    image: vuls/goval-dictionary
    auto_remove: yes
    interactive: yes
    state: started
    command: fetch-redhat "{{ item }}"
    volumes:
      - "{{ vuls_data_directory }}:/vuls"
      - "{{ vuls_data_directory }}/goval-dictionary-log:/var/log/vuls"
  with_items: "{{ redhat_oval_versions }}"

- name: fetching ubuntu oval data
  docker_container:
    name: "ubuntu-oval-{{ item }}"
    image: vuls/goval-dictionary
    auto_remove: yes
    interactive: yes
    state: started
    command: "fetch-ubuntu {{ item }}"
    volumes:
      - "{{ vuls_data_directory }}:/vuls"
      - "{{ vuls_data_directory }}/goval-dictionary-log:/var/log/vuls"
  with_items: "{{ ubuntu_oval_versions }}"

全局变量文件如下所示。 我们可以添加更多redhat_oval_versions,例如5nvd_database_years将下载 CVE 数据库直到 2017 年底:

vuls_data_directory: "/vuls_data"
nvd_database_years: 2017
redhat_oval_versions:
  - 6
  - 7
ubuntu_oval_versions:
  - 12
  - 14
  - 16

以下屏幕截图是用于 vuls 设置的 Ansible playbook 执行示例:

Vuls 设置 playbook 生效

Vuls 扫描 playbook

现在,是时候使用vuls Docker 容器执行扫描和报告了。 以下 playbook 包含了执行针对虚拟机和容器的vuls扫描以及将报告发送到 slack 和 web 的简单步骤:

- name: scanning and reporting using vuls
  hosts: vuls
  become: yes
  vars:
    vuls_data_directory: "/vuls_data"
    slack_web_hook_url: https://hooks.slack.com/services/XXXXXXX/XXXXXXXXXXXXXXXXXXXXX
    slack_channel: "#vuls"
    slack_emoji: ":ghost:"
    server_to_scan: 192.168.33.80
    server_username: vagrant
    server_key_file_name: 192-168-33-80

  tasks:
    - name: copying configuraiton file and ssh keys
      template:
        src: "{{ item.src }}"
        dest: "{{ item.dst }}"
        mode: 0400

      with_items:
         - { src: 'config.toml', dst: '/root/config.toml' }
         - { src: '192-168-33-80', dst: '/root/.ssh/192-168-33-80' } 

    - name: running config test
      docker_container:
        name: configtest
        image: vuls/vuls
        auto_remove: yes
        interactive: yes
        state: started
        command: configtest -config=/root/config.toml
        volumes:
          - "/root/.ssh:/root/.ssh:ro"
          - "{{ vuls_data_directory }}:/vuls"
          - "{{ vuls_data_directory }}/vuls-log:/var/log/vuls"
          - "/root/config.toml:/root/config.toml:ro"

    - name: running vuls scanner
      docker_container:
        name: vulsscan
        image: vuls/vuls
        auto_remove: yes
        interactive: yes
        state: started
        command: scan -config=/root/config.toml
        volumes:
          - "/root/.ssh:/root/.ssh:ro"
          - "{{ vuls_data_directory }}:/vuls"
          - "{{ vuls_data_directory }}/vuls-log:/var/log/vuls"
          - "/root/config.toml:/root/config.toml:ro"
          - "/etc/localtime:/etc/localtime:ro"
        env:
          TZ: "Asia/Kolkata"

    - name: sending slack report
      docker_container:
        name: vulsreport
        image: vuls/vuls
        auto_remove: yes
        interactive: yes
        state: started
        command: report -cvedb-path=/vuls/cve.sqlite3 -ovaldb-path=/vuls/oval.sqlite3 --to-slack -config=/root/config.toml
        volumes:
          - "/root/.ssh:/root/.ssh:ro"
          - "{{ vuls_data_directory }}:/vuls"
          - "{{ vuls_data_directory }}/vuls-log:/var/log/vuls"
          - "/root/config.toml:/root/config.toml:ro"
          - "/etc/localtime:/etc/localtime:ro"

    - name: vuls webui report
      docker_container:
        name: vulswebui
        image: vuls/vulsrepo
        interactive: yes
        volumes:
          - "{{ vuls_data_directory }}:/vuls"
        ports:
          - "80:5111"

以下文件是vuls执行扫描的配置文件。 这保存了 slack 警报的配置以及执行扫描的服务器。 可以根据vuls文档非常有效地进行配置:

[slack]
hookURL = "{{ slack_web_hook_url}}"
channel = "{{ slack_channel }}"
iconEmoji = "{{ slack_emoji }}"

[servers]

[servers.{{ server_key_file_name }}]
host = "{{ server_to_scan }}"
user = "{{ server_username }}"
keyPath = "/root/.ssh/{{ server_key_file_name }}"

以下屏幕截图是用于 vuls 扫描的 Ansible playbook 执行示例:

Vuls 扫描 playbook 生效

一旦报告容器执行完毕,根据配置选项,vuls将问题通知到相应的 slack 频道:

我们还可以访问vuls服务器 IP 地址的 Web UI 界面,以查看表格和便携格式的详细结果。 这对于管理大量服务器和规模化补丁非常有用:

我们还可以通过报告深入了解问题、严重性、操作系统等:

这可以作为基础架构代码的 CI/CD 生命周期的一部分,然后我们可以使用 Ansible Tower 或 Jenkins 作为计划扫描运行它。

为各种合规性倡议进行文件完整性检查和主机级监视的计划扫描

使用 Ansible 在主机上执行命令的许多优点之一是能够获取内部系统信息,例如:

  • 文件哈希值

  • 网络连接

  • 正在运行的进程列表

它可以作为轻量级主机入侵检测系统HIDS)。虽然在许多情况下这可能不能完全替代专门设计的 HIDS,但我们可以使用像 Facebook 的osquery这样的工具与 Ansible 一起执行相同类型的安全任务。

osquery

osquery是 Facebook 开发的操作系统仪表化框架,用 C++编写,支持 Windows、Linux、OS X(macOS)和其他操作系统。它提供了使用类似 SQL 语法的接口来查询操作系统的功能。通过使用这个,我们可以执行诸如运行进程、内核配置、网络连接和文件完整性检查等低级活动。总的来说,它就像一个主机入侵检测系统HIDS)端点安全。它提供osquery作为服务、系统交互 shell 等。因此我们可以使用它来执行集中监控和安全管理解决方案。更多关于osquery的信息请访问osquery.io

这里是对osquery的高层次概述:

使用 SQL 查询获取用户列表及其组和其他信息的osquery

以下操作手册是为了在 Linux 服务器上设置和配置osquery代理,以监视和查找漏洞、文件完整性监控和许多其他合规性活动,然后将它们记录下来发送到集中日志监控系统:

- name: setting up osquery
  hosts: linuxservers
  become: yes

  tasks:
    - name: installing osquery
      apt:
        deb: https://pkg.osquery.io/deb/osquery_2.10.2_1.linux.amd64.deb
        update_cache: yes

    - name: adding osquery configuration
      template:
        src: "{{ item.src }}"
        dest: "{{ item.dst }}"

      with_items:
        - { src: fim.conf, dst: /usr/share/osquery/packs/fim.conf }
        - { src: osquery.conf, dst: /etc/osquery/osquery.conf }

    - name: starting and enabling osquery service
      service:
        name: osqueryd
        state: started
        enabled: yes

以下fim.conf代码片段是用于文件完整性监控的包,它每 300 秒监视/home/etc/tmp目录中的文件事件。它使用安全哈希算法SHA)校验来验证更改。这可用于查找攻击者是否添加了自己的 SSH 密钥或对系统配置更改进行合规性和其他活动的审核日志更改:

{
  "queries": {
    "file_events": {
      "query": "select * from file_events;",
      "removed": false,
      "interval": 300
    }
  },
  "file_paths": {
    "homes": [
      "/root/.ssh/%%",
      "/home/%/.ssh/%%"
    ],
      "etc": [
      "/etc/%%"
    ],
      "home": [
      "/home/%%"
    ],
      "tmp": [
      "/tmp/%%"
    ]
  }
}

以下配置由osquery守护程序使用,以基于指定选项、包和自定义查询执行检查和监控。我们还使用不同的包(包含多个查询)来查找不同的监控和配置检查。

默认情况下,osquery具有多个包,用于事件响应、漏洞管理、合规性、rootkit、硬件监控等。更多详情请访问osquery.io/schema/packs

以下代码片段是osquery服务配置。根据需要可以进行修改以监视和记录osquery服务:

{
  "options": {
    "config_plugin": "filesystem",
    "logger_plugin": "filesystem",
    "logger_path": "/var/log/osquery",
    "disable_logging": "false",
    "log_result_events": "true",
    "schedule_splay_percent": "10",
    "pidfile": "/var/osquery/osquery.pidfile",
    "events_expiry": "3600",
    "database_path": "/var/osquery/osquery.db",
    "verbose": "false",
    "worker_threads": "2",
    "enable_monitor": "true",
    "disable_events": "false",
    "disable_audit": "false",
    "audit_allow_config": "true",
    "host_identifier": "hostname",
    "enable_syslog": "true",
    "audit_allow_sockets": "true",
    "schedule_default_interval": "3600" 
  },
  "schedule": {
    "crontab": {
      "query": "SELECT * FROM crontab;",
      "interval": 300
    },
    "system_profile": {
      "query": "SELECT * FROM osquery_schedule;"
    }, 
    "system_info": {
      "query": "SELECT hostname, cpu_brand, physical_memory FROM system_info;",
      "interval": 3600
    }
  },
  "decorators": {
    "load": [
      "SELECT uuid AS host_uuid FROM system_info;",
      "SELECT user AS username FROM logged_in_users ORDER BY time DESC LIMIT 1;"
    ]
  },
  "packs": {
     "fim": "/usr/share/osquery/packs/fim.conf",
     "osquery-monitoring": "/usr/share/osquery/packs/osquery-monitoring.conf",
     "incident-response": "/usr/share/osquery/packs/incident-response.conf",
     "it-compliance": "/usr/share/osquery/packs/it-compliance.conf",
     "vuln-management": "/usr/share/osquery/packs/vuln-management.conf"
  }
}

参考教程可在www.digitalocean.com/community/tutorials/how-to-monitor-your-system-security-with-osquery-on-ubuntu-16-04处查看。

可以执行该操作手册来设置 Linux 服务器上的osquery配置,以设置和记录osquery代理生成的事件:

osquery设置操作手册在执行中

目标不仅仅是设置osquery,我们可以使用日志来构建一个使用我们的 Elastic 堆栈的集中式实时监控系统。我们可以使用 Filebeat 代理将这些日志转发到我们的 Elastic 堆栈,然后我们可以查看它们并构建一个用于警报和监控的集中式仪表板。

以下是osquery生成的日志的示例,我们可以看到authorized_keys文件在 2017 年 11 月 22 日 23:59:21.000 被 Ubuntu 用户修改:

这个想法可以通过利用自动化 Ansible playbooks 对已知行动采取行动来构建一些自动化防御措施。

世界正在向容器迈进,这种监控方法可以让我们看到诸如内核安全检查和主机级文件完整性检查等底层事物。当攻击者试图绕过容器并访问主机以提升权限时,我们可以使用这种设置来检测并防御它们。

总结

容器正在迅速改变开发人员和运维团队的世界。变化的速度正在加快,在这个新世界中,安全自动化将起到重要作用。通过利用我们使用 Ansible 编写逐条命令的知识以及优秀的工具,如 Archore 和osquery,我们可以测量、分析和基准我们的容器的安全性。这使我们能够构建端到端的自动化流程,以确保、扫描和修复容器。

在下一章中,我们将探讨安全自动化的专用用例。我们将研究如何通过自动化部分任务来改进恶意软件分析。我们将特别关注集成了 Cuckoo 沙箱的轻量级动态分析工作流程,Cuckoo 沙箱是当前最流行的恶意软件分析工具之一。

自动化取证收集和恶意软件分析的实验室设置

恶意软件是安全社区面临的最大挑战之一。它影响着所有与信息系统互动的人。尽管在保护操作系统免受恶意软件侵害方面需要付出大量努力,但在恶意软件防御方面的大部分工作都是关于理解它们的来源和能力。

这是 Ansible 可以用于自动化和启用恶意软件分析专家的部分。在本章中,我们将研究各种工作流程,这些工作流程都是为了使用像 Cuckoo Sandbox 等工具对恶意软件进行分类和分析。此外,我们还将研究为隔离环境创建 Ansible Playbooks 的各种用途,以及用于收集和存储取证工件的安全备份。

为隔离环境创建 Ansible Playbooks

我们将从使用 VirusTotal 开始,并转向具有 Windows 虚拟机的隔离网络中的 Cuckoo。恶意软件分析的另一个重要方面是能够使用恶意软件信息共享平台MISP)共享威胁。我们还设置了 Viper(二进制管理和分析框架)来执行分析。

收集文件和域名恶意软件识别和分类

恶意软件分析的最初阶段之一是识别和分类。最流行的来源之一是使用 VirusTotal 进行扫描并获取恶意软件样本、域名信息等的结果。它拥有非常丰富的 API,并且许多人编写了利用该 API 进行自动扫描的自定义应用程序,使用 API 密钥来识别恶意软件类型。以下示例是在系统中设置 VirusTotal 工具、针对 VirusTotal API 扫描恶意软件样本,并识别其是否真的是恶意软件。它通常使用 60 多个杀毒扫描器和工具进行检查,并提供详细信息。

设置 VirusTotal API 工具

以下 playbook 将设置 VirusTotal API 工具(github.com/doomedraven/VirusTotalApi),它在 VirusTotal 页面本身得到了官方支持:

- name: setting up VirusTotal
  hosts: malware
  remote_user: ubuntu
  become: yes

  tasks:
    - name: installing pip
      apt:
        name: "{{ item }}"

      with_items:
        - python-pip
        - unzip

    - name: checking if vt already exists
      stat:
        path: /usr/local/bin/vt
      register: vt_status

    - name: downloading VirusTotal api tool repo
      unarchive:
        src: "https://github.com/doomedraven/VirusTotalApi/archive/master.zip"
        dest: /tmp/
        remote_src: yes
      when: vt_status.stat.exists == False 

    - name: installing the dependencies
      pip:
        requirements: /tmp/VirusTotalApi-master/requirements.txt
      when: vt_status.stat.exists == False 

    - name: installing vt
      command: python /tmp/VirusTotalApi-master/setup.py install
      when: vt_status.stat.exists == False

Playbook 的执行将下载存储库并设置 VirusTotal API 工具,这将使我们准备好扫描恶意软件样本:

用于恶意软件样本的 VirusTotal API 扫描

一旦我们准备好设置,使用 Ansible playbook 运行扫描一系列恶意软件样本就像使用 Ansible playbook 一样简单。以下 playbook 将查找并将本地恶意软件样本复制到远程系统,并对其进行递归扫描并返回结果。完成扫描后,它将从远程系统中删除样本:

- name: scanning file in VirusTotal
  hosts: malware
  remote_user: ubuntu
  vars:
    vt_api_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #use Ansible-vault
    vt_api_type: public # public/private
    vt_intelligence_access: False # True/False
    files_in_local_system: /tmp/samples/
    files_in_remote_system: /tmp/sample-file/

  tasks:
    - name: creating samples directory
      file:
        path: "{{ files_in_remote_system }}"
        state: directory

    - name: copying file to remote system
      copy:
        src: "{{ files_in_local_system }}"
        dest: "{{ files_in_remote_system }}"
        directory_mode: yes

    - name: copying configuration
      template:
        src: config.j2
        dest: "{{ files_in_remote_system }}/.vtapi"

    - name: running VirusTotal scan
      command: "vt -fr {{ files_in_remote_system }}"
      args:
        chdir: "{{ files_in_remote_system }}"
      register: vt_scan

    - name: removing the samples
      file:
        path: "{{ files_in_remote_system }}"
        state: absent

    - name: VirusTotal scan results
      debug:
        msg: "{{ vt_scan.stdout_lines }}"

使用 VirusTotal API 对恶意软件样本进行扫描的结果如下。它返回恶意软件扫描报告的哈希值和指针,以获取详细结果:

部署布谷鸟沙箱环境

布谷鸟沙箱是最流行的开源自动化恶意软件分析系统之一。它有很多集成来执行可疑文件的恶意软件分析。其设置要求包括依赖项和其他软件,如 VirtualBox、yara、ssdeep 和 volatility。此外,VM 分析是 Windows,需要一些先决条件才能进行分析。

阅读更多有关布谷鸟沙箱的信息,请访问cuckoosandbox.org

设置 Cuckoo 主机

以下 Ansible Playbook 将设置主机操作系统和 Cuckoo Sandbox 工作所需的依赖关系。这有不同的角色以安装 Ubuntu 操作系统中的所有必需软件包。

以下角色包括设置主机系统:

- name: setting up cuckoo
  hosts: cuckoo
  remote_user: ubuntu
  become: yes

  roles:
    - dependencies
    - virtualbox
    - yara
    - cuckoo
    - start-cukcoo

依赖关系角色具有很多必须安装的apt软件包以执行其他安装。然后,我们将为tcpdump软件包设置功能,以便 Cuckoo 可以访问它们进行分析:

- name: installing pre requirements
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - python
    - python-pip
    - python-dev
    - libffi-dev
    - libssl-dev
    - python-virtualenv
    - python-setuptools
    - libjpeg-dev
    - zlib1g-dev
    - swig
    - tcpdump
    - apparmor-utils
    - mongodb
    - unzip
    - git
    - volatility
    - autoconf
    - libtool
    - libjansson-dev
    - libmagic-dev
    - postgresql
    - volatility
    - volatility-tools
    - automake
    - make
    - gcc
    - flex
    - bison

- name: setting capabilitites to tcpdump
  capabilities:
    path: /usr/sbin/tcpdump
    capability: "{{ item }}+eip"
    state: present

  with_items:
    - cap_net_raw
    - cap_net_admin

然后我们将安装 VirtualBox,以便 VM 分析可以安装在 VirtualBox 中。Cuckoo 使用 VirtualBox API 与 VM 分析进行交互以执行操作:

- name: adding virtualbox apt source
  apt_repository:
    repo: "deb http://download.virtualbox.org/virtualbox/debian xenial contrib"
    filename: 'virtualbox'
    state: present

- name: adding virtualbox apt key
  apt_key:
    url: "https://www.virtualbox.org/download/oracle_vbox_2016.asc"
    state: present

- name: install virtualbox
  apt:
    name: virtualbox-5.1
    state: present
    update_cache: yes

之后,我们将安装一些额外的软件包和工具供 Cuckoo 在分析中使用:

- name: copying the setup scripts
  template:
    src: "{{ item.src }}"
    dest: "{{ item.dest }}"
    mode: 0755

  with_items:
    - { src: "yara.sh", dest: "/tmp/yara.sh" }
    - { src: "ssdeep.sh", dest: "/tmp/ssdeep.sh" }

- name: downloading ssdeep and yara releases
  unarchive:
    src: "{{ item }}"
    dest: /tmp/
    remote_src: yes

  with_items:
    - https://github.com/plusvic/yara/archive/v3.4.0.tar.gz
    - https://github.com/ssdeep-project/ssdeep/releases/download/release-2.14.1/ssdeep-2.14.1.tar.gz

- name: installing yara and ssdeep
  shell: "{{ item }}"
  ignore_errors: yes

  with_items:
    - /tmp/yara.sh
    - /tmp/ssdeep.sh

- name: installing M2Crypto
  pip:
    name: m2crypto
    version: 0.24.0

自定义脚本具有安装yarassdeep软件包的构建脚本:

# yara script
#!/bin/bash

cd /tmp/yara-3.4.0
./bootstrap
./configure --with-crypto --enable-cuckoo --enable-magic
make
make install
cd yara-python
python setup.py build
python setup.py install

# ssdeep script
#!/bin/bash

cd /tmp/ssdeep-2.14.1
./configure
./bootstrap
make
make install

最后,我们将安装 Cuckoo 和其他必需的设置,例如将用户创建到vboxusers组。配置文件取自模板,因此这些将根据 VM 分析环境进行修改:

  - name: adding cuckoo to vboxusers
    group:
      name: cuckoo
      state: present

  - name: creating new user and add to groups
    user:
      name: cuckoo
      shell: /bin/bash
      groups: vboxusers, cuckoo
      state: present
      append: yes

  - name: upgrading pip, setuptools and cuckoo
    pip:
      name: "{{ item }}"
      state: latest

    with_items:
      - pip
      - setuptools
      - pydeep
      - cuckoo
      - openpyxl
      - ujson
      - pycrypto
      - distorm3
      - pytz
      - weasyprint

  - name: creating cuckoo home direcotry
    command: "cuckoo"
    ignore_errors: yes

  - name: adding cuckoo as owner
    file:
      path: "/root/.cuckoo"
      owner: cuckoo
      group: cuckoo
      recurse: yes

以下 playbook 将复制配置并启动 Cuckoo 和 Web 服务器以执行 Cuckoo 分析:

- name: copying the configurationss
  template:
    src: "{{ item.src }}"
    dest: /root/.cuckoo/conf/{{ item.dest }}

  with_items:
    - { src: "cuckoo.conf", dest: "cuckoo.conf"}
    - { src: "auxiliary.conf", dest: "auxiliary.conf"}
    - { src: "virtualbox.conf", dest: "virtualbox.conf"}
    - { src: "reporting.conf", dest: "reporting.conf"}

- name: starting cuckoo server
  command: cuckoo -d
  ignore_errors: yes

- name: starting cuckoo webserver
  command: "cuckoo web runserver 0.0.0.0:8000"
    args:
      chdir: "/root/.cuckoo/web"
  ignore_errors: yes

设置 Cuckoo Guest

大多数设置将需要在 Windows 操作系统中执行。以下指南将帮助您为 Cuckoo 分析设置 Windows Guest VM。请参阅cuckoo.sh/docs/installation/guest/index.html

以下截图是参考,第一个适配器是 Host-only 适配器:

第二个适配器是 NAT:

一旦 Windows VM 启动,我们需要安装 VirtualBox Guest Addition 工具。这允许 Cuckoo 使用名为 VBoxManage 的命令行实用程序执行分析:

接下来,我们必须在本地安装 Python 以启动本地 Cuckoo 代理,我们可以从官方 Python 网站安装 Python:www.python.org/downloads/release/python-2714

现在从布谷鸟主机下载代理,在 Cuckoo 工作目录中的agent文件夹中可用。我们需要将其保留在 Windows VM 中,以便 Cuckoo 服务器与之交互:

然后,我们必须使用regedit命令将 Python 文件路径添加到系统启动项中。这可以通过导航到HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Current\Version\Run来完成。然后,在注册表编辑器的右侧添加新的字符串,名称为 Cuckoo,并在值部分中提供agent.py文件的完整路径:

现在,我们可以拍摄快照并更新 Cuckoo 主机中的配置。完成后,我们准备启动 Cuckoo 服务器和 Web 服务器。

以下截图是 Cuckoo Web 服务器的首页。一旦我们提交了恶意软件样本,我们就可以点击“分析”开始:

然后,将花费一些时间使用 VirtualBox Windows 虚拟机执行分析。这将根据您选择的选项执行分析:

然后,它将提供有关样本的完整详细信息。其中包括已提交文件的校验和、Cuckoo 执行分析时的运行时执行截图和其他信息:

下面的截图是恶意软件样本的行为分析,其中包括进程树的详细分析。左侧菜单包含不同的选项,如放置文件、内存转储分析和数据包分析:

在 Cuckoo 文档中了解更多有关 Cuckoo 使用的信息:docs.cuckoosandbox.org/en/latest/usage

使用 Ansible playbook 提交样本和报告

以下 playbook 将在本地系统路径中执行给定恶意软件样本文件的分析,并将报告返回给 使用 Ansible playbook:

- name: Cuckoo malware sample analysis
  hosts: cuckoo
  vars:
    local_binaries_path: /tmp/binaries

  tasks:
    - name: copying malware sample to cuckoo for analysis
      copy:
        src: "{{ local_binaries_path }}"
        dest: "/tmp/binaries/{{ Ansible_hostname }}"

    - name: submitting the files to cuckoo for analysis
      command: "cuckoo submit /tmp/binaries/{{ Ansible_hostname }}"
      ignore_errors: yes

下面的截图将恶意样本复制到 Cuckoo 分析系统,并使用 Ansible playbook 将这些文件提交进行自动化分析:

上面的截图将本地二进制文件复制到远程 Cuckoo 主机,并使用 Cuckoo 提交功能提交它们进行分析:

上述截图是我们的 Cuckoo 扫描提交使用 Ansible Playbook 提交的分析报告。

使用 Docker 容器设置 Cuckoo

这将允许我们使用 Docker 容器简化 Cuckoo 的设置。以下命令将允许我们使用 Docker 容器设置 Cuckoo 沙箱:

$ git clone https://github.com/blacktop/docker-cuckoo
$ cd docker-cuckoo
$ docker-compose up -d

下载 Docker 容器并配置它们以协同工作需要一些时间。安装完成后,我们可以使用http://localhost访问 Cuckoo:

现在,我们可以将恶意软件样本或可疑文件提交给 Cuckoo 进行分析,使用工具集进行分析,它将返回详细的分析结果。在提交样本之前,我们还可以通过选择配置选项来选择进行哪些分析。

设置 MISP 和威胁共享

恶意软件信息共享平台(MISP)是一个开源的威胁共享平台(www.misp-project.org)。它允许我们在已知的社区和组织内交换关于高级持续威胁(APT)和有针对性攻击的威胁指标(IOCs)。通过这样做,我们可以更多地了解不同的攻击和威胁,组织可以更容易地防御这些攻击。

使用卢森堡计算机事件响应中心CIRCL)定制的虚拟机是开始使用这个平台的最简单方法,其中包括完整设置的最新版本。这个虚拟机经过定制,适用于不同的环境。

VM 和培训材料可在 www.circl.lu/services/misp-training-materials 找到。

使用 Ansible playbook 设置 MISP

我们也可以使用 Ansible playbooks 进行设置。根据我们的定制使用,社区中有多个可用的 playbooks:

使用现有的 Ansible playbooks 设置 MISP 就像克隆存储库并更新所需更改和配置的变量一样简单。在执行 playbook 之前,请确保更新变量:

$ git clone https://github.com/StamusNetworks/Ansible-misp.git
$ cd Ansible-misp
$ Ansible-playbook -i hosts misp.yaml

MISP Web 用户界面

以下是 MISP 虚拟机的 Web 界面。以下是 MISP 虚拟机的默认凭据:

For the MISP web interface -> [email protected]:admin
For the system -> misp:Password1234

以下截图是恶意软件信息共享平台MISP)的主页,带有登录面板:

以下截图是 MISP 平台网页界面的主界面,包含了共享 IOCs、添加组织和执行访问控制等功能选项:

通过阅读 MISP 的文档了解不同的功能,可在 www.circl.lu/doc/misp/ 找到更多信息。

设置 Viper - 二进制管理和分析框架

Viperviper.li)是一个专为恶意软件和漏洞研究人员设计的框架。它提供了一个简单的解决方案,可以轻松地组织恶意软件和漏洞样本的集合。它为研究人员提供了 CLI 和 Web 界面,用于对二进制文件和恶意软件样本进行分析。

以下 playbook 将设置整个 Viper 框架。 它有两个角色,一个是设置运行 Viper 框架所需的依赖项,另一个是主要设置:

- name: Setting up Viper - binary management and analysis framework
  hosts: viper
  remote_user: ubuntu
  become: yes

  roles:
    - dependencies
    - setup

以下代码片段是用于设置依赖项和其他所需软件包的:

- name: installing required packages
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
    - gcc
    - python-dev
    - python-pip
    - libssl-dev
    - swig

- name: downloading ssdeep release
  unarchive:
    src: https://github.com/ssdeep-project/ssdeep/releases/download/release-2.14.1/ssdeep-2.14.1.tar.gz
    dest: /tmp/
    remote_src: yes

- name: copy ssdeep setup script
  template:
    src: ssdeep.sh
    dest: /tmp/ssdeep.sh
    mode: 0755

- name: installing ssdeep
  shell: /tmp/ssdeep.sh
  ignore_errors: yes

- name: installing core dependencies
  pip:
    name: "{{ item }}"
    state: present

  with_items:
    - SQLAlchemy
    - PrettyTable
    - python-magic
    - pydeep

在这里,我们正在使用自定义 shell 脚本来设置ssdeep,它必须执行编译和构建:

#!/bin/bash

cd /tmp/ssdeep-2.14.1
./configure
./bootstrap
make
make install

设置角色将安装 Viper 软件包,所需的依赖项,并将启动 web 服务器以访问 Viper web 用户界面:

- name: downloading the release
  unarchive:
    src: https://github.com/viper-framework/viper/archive/v1.2.tar.gz
    dest: /opt/
    remote_src: yes

- name: installing pip dependencies
  pip:
    requirements: /opt/viper-1.2/requirements.txt

- name: starting viper webinterface
  shell: nohup /usr/bin/python /opt/viper-1.2/web.py -H 0.0.0.0 &
  ignore_errors: yes

- debug:
    msg: "Viper web interface is running at http://{{ inventory_hostname }}:9090"

以下截图指的是 Viper 框架设置的 playbook 执行。并返回 web 界面 URL 以进行访问:

如果我们导航到http://192.18.33.22:9090,我们可以看到具有许多选项的 web 界面以使用此框架:

以下截图是我们分析的示例恶意软件的输出。此 Viper 框架还具有 YARA 规则集,VirusTotal API 和其他模块的模块支持,可以根据用例执行深度分析:

为收集和存储创建 Ansible playbook,同时安全备份取证工件

Ansible 是各种 bash 脚本的合适替代品。通常,对于大多数需要分析的活动,我们遵循一套固定模式:

  1. 收集正在运行的进程的日志到已知路径的文件中

  2. 定期将这些日志文件的内容复制到本地安全存储区或通过 SSH 或网络文件共享远程访问

  3. 成功复制后,旋转日志

由于涉及一些网络活动,我们的 bash 脚本通常编写为在网络连接方面具有容错性并很快变得复杂。 Ansible playbook 可以用于执行所有这些操作,同时对每个人都很容易阅读。

收集用于事件响应的日志工件

事件响应中的关键阶段是日志分析。以下 playbook 将收集所有主机的日志并将其存储到本地。这使得响应者可以进行进一步分析:

# Reference https://www.Ansible.com/security-automation-with-Ansible

- name: Gather log files
  hosts: servers
  become: yes

  tasks:
    - name: List files to grab
      find:
        paths:
          - /var/log
        patterns:
          - '*.log*'
        recurse: yes
      register: log_files

    - name: Grab files
      fetch:
        src: "{{ item.path }}"
        dest: "/tmp/LOGS_{{ Ansible_fqdn }}/"
      with_items: "{{ log_files.files }}"

以下 playbook 执行将使用 Ansible 模块在远程主机中的指定位置收集日志列表,并将其存储在本地系统中。 playbook 的日志输出如下:

数据收集的安全备份

当从服务器中收集多组数据时,将其安全地存储并进行加密备份至关重要。这可以通过将数据备份到 S3 等存储服务来实现。

以下 Ansible playbook 允许我们安装并将收集的数据复制到启用了加密的 AWS S3 服务中:

- name: backing up the log data
  hosts: localhost
  gather_facts: false
  become: yes
  vars:
    s3_access_key: XXXXXXX # Use Ansible-vault to encrypt
    s3_access_secret: XXXXXXX # Use Ansible-vault to encrypt
    localfolder: /tmp/LOGS/ # Trailing slash is important
    remotebucket: secretforensicsdatausingAnsible # This should be unique in s3

  tasks:
    - name: installing s3cmd if not installed
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes

      with_items:
        - python-magic
        - python-dateutil
        - s3cmd

    - name: create s3cmd config file
      template:
        src: s3cmd.j2
        dest: /root/.s3cfg
        owner: root
        group: root
        mode: 0640

    - name: make sure "{{ remotebucket }}" is avilable
      command: "s3cmd mb s3://{{ remotebucket }}/ -c /root/.s3cfg"

    - name: running the s3 backup to "{{ remotebucket }}"
      command: "s3cmd sync {{ localfolder }} --preserve s3://{{ remotebucket }}/ -c /root/.s3cfg"

s3cmd配置的配置文件如下所示:

[default]
access_key = {{ s3_access_key }}
secret_key = {{ s3_access_secret }}
host_base = s3.amazonaws.com
host_bucket = %(bucket)s.s3.amazonaws.com
website_endpoint = http://%(bucket)s.s3-website-%(location)s.amazonaws.com/
use_https = True
signature_v2 = True

以下截图是上传数据到 S3 存储桶的 Ansible playbook 执行:

前面的屏幕截图显示了 Ansible 播放书安装S3cmd,创建了名为secretforensicsdatausingAnsible的新桶,并将本地日志数据复制到远程 S3 存储桶。

前面的屏幕截图是播放书的结果。我们可以看到日志已成功上传到 AWS S3 中的secretforensicsdatausingAnsible S3 存储桶中。

摘要

能够自动化用于恶意软件分析的各种工作流程,使我们能够扩展分析恶意软件的数量以及进行此类大规模分析所需的资源。这是解决每天在互联网上释放的恶意软件洪流并创建有用的防御措施的一种方式。

在下一章中,我们将继续创建一个用于安全测试的 Ansible 模块。我们将从理解基础知识开始,逐步学习创建模块,并利用 OWASP ZAP 的 API 来扫描网站。到本章结束时,您将拥有一个完整的模块,可用于 Ansible CLI 或 Ansible 播放书。

为安全测试编写 Ansible 模块

Ansible 主要通过将小块代码推送到其连接的节点来工作。这些代码/程序就是我们所知的 Ansible 模块。通常在 Linux 主机的情况下,这些代码通过 SSH 复制,执行,然后从节点中删除。

正如 Ansible 开发人员指南中所述(这是所有与 Ansible 相关事物的最佳资源):

"Ansible 模块可以用任何可以返回 JSON 的语言编写。"

模块可以由 Ansible 命令行,在 playbook 中或通过 Ansible API 使用。Ansible 版本 2.4.x 已经内置了数百个模块。

查看 Ansible 文档网站上的模块索引:docs.ansible.com/ansible/latest/modules_by_category.html

目前,模块有 20 多个类别,包括云、存储、远程管理和 Windows 等类别。

有时候,尽管有了所有这些模块,您可能仍然需要编写自己的模块。本章将带您编写一个可以与 Ansible playbook 一起使用的模块。

Ansible 有一个非常详细的开发指南(docs.ansible.com/ansible/latest/dev_guide/index.html),如果您计划贡献您的模块以与 Ansible 一起发布,这是开始的最佳位置。

本章完全不打算取代它。考虑到,如果您计划为内部使用编写模块,并且您不介意分发它们,那么本章为您提供了一个简单易行的路径,我们最终将获得一个可用的模块,用于启用安全自动化,这一直是我们的目标。

我们将研究以下内容:

  • 如何设置开发环境

  • 编写一个 Ansible hello world 模块以了解基础知识

  • 寻求进一步帮助的地方

  • 定义一个安全问题陈述

  • 通过编写我们自己的模块来解决这个问题

除此之外,我们将尝试理解并试图回答以下问题:

  • 模块的良好使用案例是什么?

  • 何时使用角色才有意义?

  • 模块与插件有何不同?

让我们从一个简单的 hello world 模块开始。

开始使用一个简单的 hello world Ansible 模块

我们将向自定义模块传递一个参数,并根据此参数的执行情况显示模块执行成功或失败。

由于这一切对我们来说都是新的,我们将查看以下内容:

  • hello world 模块的源代码

  • 该模块的成功和失败输出

  • 我们将用来调用它的命令

在我们开始之前,所有这些都基于 Ansible 开发人员指南!以下代码是用 Python 编写的。

代码

我们在许多脚本任务中使用 Python,但我们并不是专家。但我们相信这段代码足够简单易懂:

from ansible.module_utils.basic import AnsibleModule

module = AnsibleModule(
    argument_spec=dict(
        answer=dict(choices=['yes', 'no'], default='yes'),
    )
)

answer = module.params['answer']
if answer == 'no':
    module.fail_json(changed=True, msg='Failure! We failed because we answered no.')

module.exit_json(changed=True, msg='Success! We passed because we answered yes.')
  1. 我们正在导入一些模块。

  2. 第二部分只是我们需要声明模块将接受的参数。

  3. 在我们的代码中,我们可以引用参数的方式就像我们取得了 answer 变量的值一样。

  4. 基于答案,如果是 no,我们表示失败。

  5. 如果答案是 yes,我们表示成功。

让我们看看如果我们提供答案为 yes 时的输出是什么样子:

$ ANSIBLE_LIBRARY=. ansible -m ansible_module_hello_world.py -a answer=yes localhost

 [WARNING]: provided hosts list is empty, only localhost is available

localhost | SUCCESS => {
    "changed": true,
    "msg": "Success! We passed because we answered yes."
}

如果答案是 no

$ ANSIBLE_LIBRARY=. ansible -m ansible_module_hello_world -a answer=no localhost

 [WARNING]: provided hosts list is empty, only localhost is available

localhost | FAILED! => {
    "changed": true,
    "failed": true,
    "msg": "Failure! We failed because we answered no."
}

输出中的主要区别是指示的 SUCCESSFAILED 状态以及我们提供的消息。

由于到目前为止我们还没有设置开发环境,所以我们为此命令设置了一个环境变量:

  • ANSIBLE_LIBRARY=. 表示在当前目录中搜索要执行的模块

  • 使用 -m,我们调用我们的模块

  • 使用 -a,我们传递模块参数,在这种情况下是可能值为 yesno

  • 我们以我们要在其上运行模块的主机结束,对于此示例,它是本地的

尽管 Ansible 是用 Python 编写的,请注意模块可以用任何能够返回 JSON 消息的语言编写。对于 Ruby 程序员来说,一个很好的起点是 Github 上的 Ansible for Rubyists (github.com/ansible/ansible-for-rubyists) 仓库。Packt 出版的《Learning Ansible》第五章也涵盖了这一点。

设置开发环境

Ansible 2.4 的主要要求是 Python 2.6 或更高版本和 Python 3.5 或更高版本。如果你安装了其中之一,我们可以按照简单的步骤进行开发环境设置。

来自 Ansible 开发者指南:

  1. 克隆 Ansible 仓库:$ git clone https://github.com/ansible/ansible.git

  2. 切换到仓库根目录:$ cd ansible

  3. 创建虚拟环境:$ python3 -m venv venv(或对于 Python 2 $ virtualenv venv

  4. 注意,这需要你安装 virtualenv 包:$ pip install virtualenv

  5. 激活虚拟环境:$ . venv/bin/activate

  6. 安装开发要求:$ pip install -r requirements.txt

  7. 对每个新的 dev shell 进程运行环境设置脚本:$ . hacking/env-setup

此时你应该得到一个 venv 提示符。以下是设置开发环境的一个简单 Playbook。

以下 Playbook 将通过安装和设置虚拟环境来设置开发环境:

- name: Setting Developer Environment
  hosts: dev
  remote_user: madhu
  become: yes
  vars:
    ansible_code_path: "/home/madhu/ansible-code"

  tasks:
    - name: installing prerequirements if not installed
      apt:
        name: "{{ item }}"
        state: present
        update_cache: yes

      with_items:
        - git
        - virtualenv
        - python-pip

    - name: downloading ansible repo locally
      git:
        repo: https://github.com/ansible/ansible.git
        dest: "{{ ansible_code_path }}/venv"

    - name: creating virtual environment
      pip:
        virtualenv: "{{ ansible_code_path }}"
        virtualenv_command: virtualenv
        requirements: "{{ ansible_code_path }}/venv/requirements.txt"

以下屏幕截图显示了使用 Python 虚拟环境编写自己的 Ansible 模块设置开发环境的 Playbook 执行:

计划和需要注意的事项

Ansible 开发者指南中有一个关于如何开发模块的部分 (docs.ansible.com/ansible/latest/dev_guide/developing_modules.html#should-you-develop-a-module).

在该部分中,他们有多个关于继续开发模块前需要注意的要点。

是否已经存在类似的模块?检查当前的模块是否已经做了你计划构建的事情总是一个好主意。好消息是,到目前为止还没有人建立一个开放式 Web 应用程序安全项目OWASPZed Attack ProxyZAP)模块。

是否有人已经在类似的 Pull Request 上工作?再次强调,也许这个模块还没有发布,但这并不意味着人们还没有在上面工作。文档提供了三个方便的链接,以检查是否已经有类似的 PR 存在。

另外,它询问是否应该查看一个动作插件或角色,而不是一个模块。我们认为开发模块对我们来说是有道理的主要原因是它将在节点上运行。如果 ZAP 已经在运行,ZAP 提供了一个 API 端点,我们打算让我们的模块可以方便地在托管的 ZAP 实例上运行 ZAP 扫描。

所以,现在的计划是:

  1. 创建一个模块,将连接到托管的 ZAP 实例。

  2. 为模块提供两个主要信息:

    • 托管 ZAP 的 IP 地址

    • 扫描目标 URL

  3. 通过调用该模块,我们将有一个任务来扫描目标应用程序。

OWASP ZAP 模块

OWASP ZAP 有一个我们可以使用的 API。此外,有一个用于消费 API 的 Python 模块。我们将尝试使用它来学习如何编写自己的 Ansible 模块。

使用 Docker 创建 ZAP

对于我们的开发,让我们使用一个 Docker 容器来启动 ZAP。由于我们计划使用 API,我们将在无头模式下运行容器:

$ docker run -u zap -p 8080:8080 -i owasp/zap2docker-stable zap.sh -daemon -host 0.0.0.0 -port 8080 -config api.disablekey=true -config api.addrs.addr.name=.* -config api.addrs.addr.regex=true

命令的解释

  • 当我们进行开发时,我们可以禁用 API 密钥:-config api.disablekey=true

  • 允许从任何 IP 访问 API:-config api.addrs.addr.name=.* -config api.addrs.addr.regex=true

  • 监听端口 8080

如果一切正常,你将看到以下输出:

创建一个易受攻击的应用程序

对于一个易受攻击的应用程序,我们可以托管一个自己的,但让我们使用同一个在线易受攻击的应用程序,我们在 第五章 中用于 OWASP ZAP + Jenkins 集成的:自动化 *Web 应用程序安全测试使用 OWASP ZAP - *testphp.vulnweb.com/

Ansible 模块模板

我们将使用模块开发指南中给出的示例代码来开始:docs.ansible.com/ansible/latest/dev_guide/developing_modules_general.html#new-module-development

这个模板有一个注释齐全的代码,写得让我们很容易开始。代码分为以下几部分:

  • 元数据

  • 文档化模块

  • 我们将要使用的函数

元数据

这个部分包含有关模块的信息:

ANSIBLE_METADATA = {
    'metadata_version': '1.1',
    'status': ['preview'],
    'supported_by': 'community'
}

这个模块没有官方支持,因此使用了 community

文档化模块

模块文档是从模块代码本身生成的。 现在创建的模块必须有 DOCUMENTATION 文档字符串。

开始的最简单方法是查看此示例:github.com/ansible/ansible/blob/devel/examples/DOCUMENTATION.yml

此处所需的字段清单为:

  • module:模块名称

  • short_description:简短描述

  • description:描述

  • version_added:由 X.Y 指示

  • author:您的姓名和 Twitter/GitHub 用户名

  • options:模块支持的每个选项

  • notes:模块用户应该注意的任何其他事项

  • requirements:我们列出额外的包要求

有关字段的更多详细信息,请访问docs.ansible.com/ansible/latest/dev_guide/developing_modules_documenting.html#fields

源代码模板

这里有一些我们将用来编写模块的源代码片段。我们已经讨论了元数据和文档部分。我们还需要为示例和模块将返回的内容编写文档字符串。

我们的导入模块 - 我们可以在这里导入构建模块所需的所有模块:

from ansible.module_utils.basic import AnsibleModule

主要代码块 - 在函数 run_module 中,我们进行以下工作:

  1. 定义模块正常工作所需的所有参数。

  2. 初始化结果字典。

  3. 创建 AnsibleModule 对象并传递可能需要的公共属性:

def run_module():
    # define the available arguments/parameters that a user can pass to
    # the module
    module_args = dict(
        name=dict(type='str', required=True),
        new=dict(type='bool', required=False, default=False)
    )

    # seed the result dict in the object
    # we primarily care about changed and state
    # change is if this module effectively modified the target
    # state will include any data that you want your module to pass back
    # for consumption, for example, in a subsequent task
    result = dict(
        changed=False,
        original_message='',
        message=''
    )

    # the AnsibleModule object will be our abstraction working with Ansible
    # this includes instantiation, a couple of common attr would be the
    # args/params passed to the execution, as well as if the module
    # supports check mode
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )
  1. 处理异常和结果:
 # during the execution of the module, if there is an exception or a
    # conditional state that effectively causes a failure, run
    # AnsibleModule.fail_json() to pass in the message and the result
    if module.params['name'] == 'fail me':
        module.fail_json(msg='You requested this to fail', **result)

    # in the event of a successful module execution, you will want to
    # simple AnsibleModule.exit_json(), passing the key/value results
    module.exit_json(**result)

只需记住以下几点:

  • 如果遇到任何错误或异常,我们调用 AnsibleModule 对象的 fail_json 函数

  • 如果一切顺利,我们调用相同对象的 exit_json 函数

调用我们的功能完成代码:

def main():
    run_module()

if __name__ == '__main__':
    main()

目前,我们已经准备好了以下工作,并准备进行下一步:

模块代码模板 就绪
我们需要扫描的易受攻击应用程序(目标) 就绪
启用 API 并在无头模式下运行的 OWASP ZAP 代理(主机和端口) 就绪
我们可以参考的 OWASP ZAP Python API 代码 待定

我们希望专注于编写 Ansible 模块,而不是花时间学习完整的 OWASP ZAP API。虽然我们建议您这样做,但等到模块正常工作后再学习也可以。

OWASP ZAP Python API 示例脚本

OWASP ZAP Python API 包带有一个非常实用的脚本,完整涵盖了对 Web 应用程序进行爬行和主动扫描的代码。

github.com/zaproxy/zaproxy/wiki/ApiPython#an-example-python-script下载代码进行学习。

这里有一些我们目前感兴趣的样本代码片段。 导入用于 OWASP ZAP 的 Python API 客户端。 这通过 pip install python-owasp-zap-v2.4 安装:

from zapv2 import ZAPv2

现在,我们连接到 ZAP 实例 API 端点。我们可以将主机和端口提供给我们模块的 OWASP ZAP 实例作为参数:

zap = ZAPv2(apikey=apikey, proxies={'http': 'http://127.0.0.1:8090', 'https': 'http://127.0.0.1:8090'})

提供我们想要扫描的网站的主机/IP 地址:

zap.urlopen(target)
# Give the sites tree a chance to get updated
time.sleep(2)

print 'Spidering target %s' % target
scanid = zap.spider.scan(target)

# Give the Spider a chance to start
time.sleep(2)
while (int(zap.spider.status(scanid)) < 100):
    print 'Spider progress %: ' + zap.spider.status(scanid)
    time.sleep(2)

print 'Spider completed'
# Give the passive scanner a chance to finish
time.sleep(5)

print 'Scanning target %s' % target
scanid = zap.ascan.scan(target)
while (int(zap.ascan.status(scanid)) < 100):
    print 'Scan progress %: ' + zap.ascan.status(scanid)
    time.sleep(5)

print 'Scan completed'

# Report the results

print 'Hosts: ' + ', '.join(zap.core.hosts)
print 'Alerts: '
pprint (zap.core.alerts())

此代码是我们在模块中使用的一个很好的起始模板。

在这里,我们准备好了可以参考的 OWASP ZAP Python API 代码。

连接到 ZAP 实例。此时,我们复制了代码的重要部分,即:

  1. 连接到目标。

  2. 启动爬虫和主动安全扫描。

但是我们很快遇到了一个错误。在异常期间我们返回了一个字符串,这显然不符合 Ansible 所需的 JSON 格式。

这导致了一个错误,我们没有足够的信息来采取行动

Ansible 模块应该只返回 JSON,否则您可能会看到像上面那样的难以理解的错误

docs.ansible.com/ansible/latest/dev_guide/developing_modules_best_practices.html#conventions-best-practices-and-pitfalls中快速阅读惯例、最佳实践和陷阱为我们解释了问题。

如果您在编写模块过程中遇到任何问题,我们强烈建议您阅读本指南:docs.ansible.com/ansible/latest/dev_guide/developing_modules_best_practices.html#conventions-best-practices-and-pitfalls

使用 OWASP ZAP API 文档来了解更多信息:github.com/zaproxy/zaproxy/wiki/ApiGen_Index

完整的代码清单

此代码也可以在 GitHub 上找到(github.com/appsecco/ansible-module-owasp-zap)。所有注释、元数据和文档字符串都已从此列表中删除:

try: 
    from zapv2 import ZAPv2
    HAS_ZAPv2 = True
except ImportError:
    HAS_ZAPv2 = False 

from ansible.module_utils.basic import AnsibleModule
import time
def run_module():
    module_args = dict(
        host=dict(type='str', required=True),
        target=dict(type='str', required=True)
    )

    result = dict(
        changed=False,
        original_message='',
        message=''
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    if not HAS_ZAPv2:
        module.fail_json(msg = 'OWASP python-owasp-zap-v2.4 required. pip install python-owasp-zap-v2.4')

if module.check_mode:
    return result
host = module.params['host']
target = module.params['target']
apikey = None
zap = ZAPv2(apikey=apikey, proxies={'http':host,'https':host})
zap.urlopen(target)
try:
    scanid = zap.spider.scan(target)
    time.sleep(2)
    while (int(zap.spider.status(scanid)) < 100):
        time.sleep(2)
except:
    module.fail_json(msg='Spidering failed')
time.sleep(5)

try:
    scanid = zap.ascan.scan(target)
    while (int(zap.ascan.status(scanid)) < 100):
        time.sleep(5)
except:
    module.fail_json(msg='Scanning failed')

result['output'] = zap.core.alerts()
result['target'] = module.params['target']
result['host'] = module.params['host']
module.exit_json(**result)

def main():
    run_module()
if __name__ == '__main__':
    main()

根据被爬取和扫描的网站不同,这可能需要一些时间来完成。在执行结束时,您将在results['output']中获得扫描结果。

运行模块

我们运行模块的选择如下:

  1. 我们将其复制到 Ansible 库的标准路径。

  2. 每当我们有我们的模块文件时,我们都会提供一个路径到 Ansible 库。

  3. 通过 playbook 运行此文件。

以下命令将调用我们的模块以供我们测试并查看结果:

ansible -m owasp_zap_test_module localhost -a "host=http://172.16.1.102:8080 target=http://testphp.vulnweb.com" -vvv

命令的解释

  • ansible命令行

  • -m用于提供模块名称,即owasp_zap_test_module

  • 它将在localhost上运行

  • -a允许我们传递hosttarget模块参数

  • -vvv 用于输出的详细程度。

模块的 playbook

这是一个简单的 playbook,用于测试一切是否正常运行:

- name: Testing OWASP ZAP Test Module
  connection: local
  hosts: localhost
  tasks:
  - name: Scan a website
    owasp_zap_test_module:
      host: "http://172.16.1.102:8080"
      target: "http://testphp.vulnweb.com"

使用此命令执行 playbook:

ansible-playbook owasp-zap-site-scan-module-playbook.yml

重要的一点要记住的是,仅仅因为我们有一个可用的模块,并不意味着 Ansible 的优秀工程师们会自动接受我们的模块并将其随软件的下一个版本一起发布。我们的模块要能够被所有人使用,还需要进行大量的额外工作。

通常,最好的指南是本章前面提到的开发人员指南。

我们的模块中可以添加的一个简单的功能是能够将 API 密钥作为参数发送。大多数用于常规扫描的 ZAP 实例已经配置了这个。此外,当在 playbook 中存储时,此密钥可以由 Ansible vault 保护。

添加 API 密钥作为参数

只需做出以下更改,我们就能够将apikey添加为一个参数:

  • 首先,我们将其添加到第 76-78 行的module_args字典中:apikey=dict(type='str',required=False,default=None)

  • 然后,我们检查 module.params['apikey'] 是否设置为None的值

  • 如果不是,将其设置为 apikey = module.params['apikey']

  • 现在,如果模块与 Ansible 命令行工具一起使用,请将其与 targethost 一起传递,如果在 playbook 中使用,请在那里传递

将扫描类型添加为参数

如果你迄今为止一直在跟进,你可能意识到我们运行的扫描是一个主动扫描。扫描器会对目标发送攻击流量进行主动扫描。

由于这个事实,有时如果网站很大,完成可能需要很长时间。

有关主动扫描的更多信息,请访问github.com/zaproxy/zap-core-help/wiki/HelpStartConceptsAscan

我们希望添加一个参数,以便能够提供要运行的扫描类型。到目前为止,我们有两种类型:

  • 主动:发送攻击流量

  • 被动扫描:在蜘蛛爬取阶段下载的所有站点文件都会被解析

我们首先将其作为module_args的一部分添加:

module_args = dict(
    host=dict(type='str', required=True),
    target=dict(type='str', required=True),
    apikey=dict(type='str',required=False,default=None),
    scantype=dict(default='passive', choices=['passive','active'])
)

新添加的行已加粗以突出显示更改。请注意,我们现在定义了默认值,并且当前只允许这个参数有两个选择。因此,如果未设置任何值,则执行更快、更少侵入性的被动扫描。

我们需要将模块参数的值放入名为scantype的变量中:

scantype = module.params['scantype']

现在逻辑改变以适应两个可能的值:

if scantype == 'active':
    try:
        scanid = zap.ascan.scan(target)
        while (int(zap.ascan.status(scanid)) < 100):
            time.sleep(5)
    except:
        module.fail_json(msg='Active Scan Failed')
else:
    try:
        while (int(zap.pscan.records_to_scan) > 0):
            time.sleep(2)
    except:
        module.fail_json(msg='Passive Scan Failed')

如果scantype已设置且值为active,那么它才会进行主动扫描。这个改进使我们的模块更加灵活:

Using the new and improved module in our playbook
- name: Testing OWASP ZAP Test Module
  connection: local
  hosts: localhost
  tasks:
  - name: Scan a website
    owasp_zap_test_module:
      host: "http://172.16.1.102:8080"
      target: "http://testphp.vulnweb.com"
      scantype: passive
    register: output
  - name: Print version
    debug:
      msg: "Scan Report: {{ output }}"

使用 Ansible 作为 Python 模块

直接在您的 Python 代码中使用 Ansible 是一种与其交互的强大方式。请注意,使用 Ansible 2.0 及更高版本时,这并不是最简单的方法。

在继续之前,我们应该告诉你核心 Ansible 团队对直接使用 Python API 的看法

从 http://docs.ansible.com/ansible/latest/dev_guide/developing_api.html

请注意,虽然我们提供了此 API,但它不适用于直接使用,它在这里是为了支持 Ansible 命令行工具。我们尽量不会进行破坏性更改,但如果对 Ansible 工具集有意义,我们保留随时进行更改的权利。

以下文档提供给那些仍然希望直接使用 API 的人,但请注意,这不是 Ansible 团队支持的内容。

以下代码来自 Ansible 开发者指南文档:docs.ansible.com/ansible/latest/dev_guide/developing_api.html

import json
from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars.manager import VariableManager
from ansible.inventory.manager import InventoryManager
from ansible.playbook.play import Play
from ansible.executor.task_queue_manager import TaskQueueManager
from ansible.plugins.callback import CallbackBase

一旦所有的初始工作都完成了,任务将会这样执行:

try</span>:
    tqm = TaskQueueManager(
              inventory=inventory,
              variable_manager=variable_manager,
              loader=loader,
              options=options,
              passwords=passwords,
              stdout_callback=results_callback,  # Use our custom callback instead of the ``default`` callback plugin
          )
    result = tqm.run(play)

在 Ansible 2.0 之前,整个过程要简单得多。但是这段代码现在不再适用了:

import ansible.runner

runner = ansible.runner.Runner(
   module_name='ping',
   module_args='',
   pattern='web*',
   forks=10
)
datastructure = runner.run()

总结

在这一章中,我们创建了一个用于安全自动化的工作中的 Ansible 模块。我们首先创建了一个类似于 hello world 的模块,虽然功能不多,但帮助我们理解了一个模块文件可能是什么样子的布局。我们按照 Ansible 开发者指南的说明设置了一个能够进行模块开发的环境。我们阐述了我们对模块的需求,并选择了 OWASP ZAP 作为创建模块的可能候选者。

使用开发者文档中的模板等辅助工具,我们创建了该模块,并学习了如何使用 Ansible CLI 或 playbook 使用它。我们在原始代码中添加了几个选项,以使模块更加实用和灵活。现在我们有了一个能够连接到任何允许使用 API 密钥访问并在目标上执行被动或主动扫描的 OWASP ZAP Ansible 模块。

这是本书的倒数第二章。在下一章中,我们将查看额外的参考资料,使用 Ansible Vault 保护我们的机密信息,以及一些已经使用 Ansible 实现的世界级安全自动化的参考资料。

Ansible 安全最佳实践、参考资料和深入阅读

上一章。我们终于到达了这里。是时候反思我们一起学到了什么了。是时候列出你应该从哪里开始了。最重要的是,有一些主题将增强您使用 Ansible 的体验。

本章中我们将涵盖的一些主题如下:

  • 使用 Ansible Vault 以及为什么应该将所有机密信息存储在 vault 中

  • 使用 Ansible Galaxy 分享 playbooks 和角色

  • 保护主控制器

  • 附加参考资料

  • 期待 Ansible 2.5 中的新功能和即将推出的内容。

使用 Ansible Vault

Ansible Vault 是一个命令行实用程序,默认与 Ansible 一起安装。它允许我们加密诸如密钥、凭据、密码等机密信息以包含在我们的 playbooks 中。通过这样做,我们还可以使用这些加密文件与他人共享,因为它们包含密码保护以访问加密数据。我们可以使用此功能在我们的 playbooks 中加密变量、模板和文件。

Ansible 版本 2.3 支持使用 Ansible 单个加密变量以及带有 !vault 标签的 Ansible 单个加密变量来加密单个变量。我们将在下一节中看到一些示例,了解我们将如何在 playbooks 中使用它。

docs.ansible.com/ansible/latest/vault.html 中了解更多关于 Ansible Vault 的信息。

由于这是一种非常简单而强大的存储和管理机密数据的方式,因此在我们的 playbooks 中使用 Ansible Vault 存储所有机密信息非常重要。

一些非常好的用例包括我们如何在不更改版本控制系统、CI/CD 集成管道等情况下使用这些 playbooks。

如何在变量和文件中使用 Ansible Vault

以下示例演示了如何在我们的 playbook 变量文件中使用机密。

让我们以在 Ubuntu 操作系统中安装 MySQL 服务器为例,使用以下 playbook。根据 Ansible 文档,最好将 Vault 变量和普通变量分开存储。

以下代码片段是安装 MySQL 服务器的高级文件结构,包括根密码:

├── group_vars
│   └── mysql.yml # contains vault secret values
├── hosts
├── main.yml
└── roles
    └── mysqlsetup
        └── tasks
            └── main.yml

现在我们可以看到 mysqlsetup 角色包含以下任务,需要 mysql_root_password 变量,该变量包含 MySQL 服务器的根密码:

- name: set mysql root password
  debconf:
    name: mysql-server
    question: mysql-server/root_password
    value: "{{ mysql_root_password | quote }}"
    vtype: password

- name: confirm mysql root password
  debconf: 
    name: mysql-server
    question: mysql-server/root_password_again
    value: "{{ mysql_root_password | quote }}"
    vtype: password

- name: install mysqlserver
  apt:
    name: "{{ item }}"
    state: present
    update_cache: yes

  with_items:
   - mysql-server
   - mysql-client

现在,如果我们查看 group_vars/main.yml 文件,其内容如下所示。它包含用于 playbook 中的 secrets 变量,称为 mysql_root_password

mysql_root_password: supersecretpassword​

要加密 vault 文件,我们将使用以下命令,然后提示输入密码进行保护:

$ ansible-vault encrypt group_vars/mysql.yml

New Vault password: 
Confirm New Vault password: 
Encryption successful

现在,如果我们查看 vault 内容,它看起来如下,使用给定密码进行 AES256 加密:

$ cat group_vars/main.yml 

$ANSIBLE_VAULT;1.1;AES256
30356164636532373531656636666330316330373764323938653462376630653038386531303362
3631623330663939666235326638343164393564303630320a383338613635623533383236613339
65333164663262626565333231343861613764383238363136333639643637353439623832356263
3038343830373137650a633261653037306438633030326165356436623832386230373030326131
34353534313337616561643333613435396636363836396239306139383330333539653138343231
6430656638626162306463333736666536336139643637376636

现在,要执行 playbook,请运行以下命令,它将提示输入 vault 密码:

$ ansible-playbook --ask-vault-pass -i hosts main.yml

以下截图显示我们在执行 Ansible Playbook 时提供了 Vault 密码。

  • 我们还可以通过指定标志在 playbook 执行中传递 ansible-vault 密码文件,这有助于我们的持续集成和流水线平台。

  • 以下文件包含用于加密 mysql.yml 文件的密码:

$ cat ~/.vaultpassword

thisisvaultpassword

确保为此文件提供适当的权限,以便其他人无法使用 chmod 访问该文件。另外,将该文件添加到你的 .gitignore 中是一个好习惯,这样在推送 playbook 时不会进行版本控制。

保险库密码文件可以是可执行脚本,它可以检索存储在安全位置的数据,而不必在磁盘上以明文形式保存密钥,并依赖文件权限来保护它。

要通过命令行传递保险库密码文件,请在执行 playbook 时使用以下命令:

$ ansible-playbook --vault-password-file ~/.vaultpassword -i hosts main.yml

我们还可以使用系统环境变量,例如 ANSIBLE_VAULT_PASSWORD_FILE=~/.vaultpassword,Ansible 在执行 playbook 时会使用它。

我们可以使用 ansible-vault 进行多个操作,例如使用 create 参数创建文件。这默认情况下会加密文件的内容。它还将打开默认文本编辑器来编辑文件:

$ ansbile-vault create vault.yml

New Vault password: 
Confirm New Vault password: 

我们可以使用 view 命令来查看明文中的保险库加密信息。

$ ansible-vault view vault.yml
Vault password: 
API_KEY: KANGEG4TNG434G43HG43H9GH344FEGEW

要更改内容,我们可以使用 ansible-vault 中的 edit 子命令

$ ansible-vault edit vault.yml

Vault password: 

我们还可以使用以下命令解密秘密信息

$ ansible-vault decrypt vault.yml

Vault password: 
Decryption successful

要更改密钥轮换的保险库密码,我们可以使用 rekey 选项:

$ ansible-vault rekey vault.yml
Vault password: 
New Vault password: 
Confirm New Vault password: 
Rekey successful

Ansible Vault 单个加密变量

此功能可从 Ansible 版本 2.3 开始使用。它允许我们在 YAML 文件中使用带有 !vault 标记的保险库变量;我们将看到一个简单的示例和用例。

以下 playbook 用于使用 ViewDNS API 执行反向 IP 查找。

我们想要保护 api_key,因为它包含敏感信息。我们使用 ansible-vault encrypt_string 命令执行此加密。在这里,我们使用了 echo-n 标志来删除换行符:

$ echo -n '53ff4ad63849e6977cb652763g7b7c64e2fa42a' | ansible-vault encrypt_string --stdin-name 'api_key'

然后,我们可以像以下代码块中所示,将变量放在 playbook 变量中,并使用 ansible-playbook 普通执行 playbook,使用 --ask-vault-pass 选项:

- name: ViewDNS domain information
  hosts: localhost
  vars:
    domain: google.com
    api_key: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          36623761316238613461326466326162373764353437393733343334376161336630333532626465
          6662383435303930303164353664643639303761353664330a393365633237306530653963353764
          64626237313738656530373639653739656564316161663831653431623832336635393637653330
          6632663563363264340a323537356166653338396135376161323435393730306133626635376539
          37383861653239326336613837666237636463396465393662666561393132343166666334653465
          6265386136386132363534336532623061646438363235383334
    output_type: json

  tasks:
    - name: "getting {{ domain }} server info"
      uri:
        url: "https://api.viewdns.info/reverseip/?host={{ domain }}&apikey={{ api_key }}&output={{ output_type }}"
        method: GET
      register: results

    - debug:
        msg: "{{ results.json }}"

然后,在我们提供给它指定的密码后,将自动解密执行的 playbook。

下面的截图显示了在提示输入保险库密码后执行 playbook。

docs.ansible.com/ansible/2.4/vault.html#use-encrypt-string-to-create-encrypted-variables-to-embed-in-yaml 阅读有关 encrypt_string 选项的更多信息。

Ansible Tower 中的 Ansible Vault 使用

Ansible Tower 已经与 Ansible Vault 集成。

下面的截图指的是在 Ansible Tower 中创建新凭据。我们还可以添加 Vault 密码,这样用户就可以使用更安全的方式存储和检索密钥。

设置和使用 Ansible Galaxy

Ansible Galaxy,也称为 Galaxy,是一个官方集中式中心,用于查找、共享和重用 Ansible 角色。这允许社区分享和合作使用 Ansible playbook,并允许新用户快速开始使用 Ansible。要与社区共享我们自定义编写的角色,我们可以使用 GitHub 认证将它们发布到 Ansible Galaxy。

这些角色也可以在 galaxy.ansible.com 上访问,也可以使用一个名为 ansible-galaxy 的命令行工具进行访问,该工具随 Ansible 一起安装:

我们可以使用不同的参数(如作者、平台、标签等)查找角色。这使用户能够了解此角色是否适用于其分发和版本,需要哪个 Ansible 版本以及其他信息。

下面的截图展示了如何使用 ansible-galaxy CLI 执行不同的操作,比如搜索和安装:

从文档中阅读有关 Ansible Galaxy 的更多信息 docs.ansible.com/ansible/latest/galaxy.html

了解更多有关 Galaxy 使用的信息,请访问 galaxy.ansible.com/intro

使用 Ansible Galaxy 角色

要从 Ansible Galaxy 网站下载角色,我们可以运行以下命令,其中 usernamerole_name 是选项:

$ ansible-galaxy install username.role_name

下面的命令将由用户 angstwad 下载 docker_ubuntu 角色:

$ ansible-galaxy install angstwad.docker_ubuntu

- downloading role 'docker_ubuntu', owned by angstwad
- downloading role from https://github.com/angstwad/docker.ubuntu/archive/v3.3.4.tar.gz
- extracting angstwad.docker_ubuntu to /home/ubuntu/.ansible/roles/angstwad.docker_ubuntu
- angstwad.docker_ubuntu (v3.3.4) was installed successfully

要在 Ubuntu 上使用此角色安装 Docker,只需在我们的 playbook 中包含此角色并执行它即可:

- name: Run docker.ubuntu
 hosts: docker
 become: yes

 roles:
 - angstwad.docker_ubuntu $ ansible-playbook -i hosts main.yml

我们可以通过指定 GitHub URL 直接从 GitHub 安装或包含角色。这允许使用私有版本控制系统作为 playbook 角色的本地清单:

$ ansible-galaxy install git+https://github.com/geerlingguy/ansible-role-composer.git

将我们的角色发布到 Ansible Galaxy

要将我们自己的角色发布到 Ansible Galaxy,我们需要一个 GitHub 账户,该账户将用于验证 Ansible Galaxy,GitHub 中的版本控制存储库将是存储我们角色的地方。

以下步骤用于在 Ansible Galaxy 中创建和共享新角色:

  1. 首先,在 GitHub 中创建一个新存储库,然后使用以下命令将其克隆到本地:
$ git clone https://[email protected]/username/ansible-role-docker.git docker
  1. 然后,我们可以使用 ansible-galaxy 命令创建角色结构:
$ ansible-galaxy init docker --force
- docker was created successfully

# The structure looks like below
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── README.md
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
 └── main.yml
  1. 现在,我们可以像之前创建它们一样添加任务和其他步骤。以下是 Ansible Galaxy 自身的一些良好实践(galaxy.ansible.com/intro#good):

    1. README.md 中提供清晰的文档。

    2. meta/main.yml 中提供准确的信息。

    3. meta/main.yml 中包含依赖项。

    4. 以角色名为变量名加上前缀。

    5. 将您的角色与 Travis CI 集成。

  2. 元文件包含将在 Ansible Galaxy 中发布角色所使用的信息;我们可以根据需要修改它。以下是一个示例:

---
galaxy_info:
  author: USERNAME
  description: Quick and easy docker installer.
  company: ORG
  license: MIT
  min_ansible_version: 1.9
  platforms:
  - name: Ubuntu
    versions:
    - xenial
    - trusty
  galaxy_tags:
    - docker
    - installer
    - ubuntu
dependencies:
  - { role: username.common, some_parameter: 3 }
  1. 然后,我们可以将角色推送到 GitHub,并通过在门户中添加新角色来导入到 Ansible Galaxy 中:

有关如何编写可重用角色以及有关编写社区角色的更多详细信息,请参阅 docs.ansible.com/ansible/latest/playbooks_reuse.html

Ansible Galaxy 本地设置

要在本地设置 Ansible Galaxy,我们有不同的方法。大多数安装在幕后使用容器。以下步骤描述了如何使用 dockerdocker-compose 安装 Ansible Galaxy 本地设置。

在继续之前,我们需要以下先决条件:

  • Ansible 2.4+

  • Docker

  • docker-py Python 模块

  • docker-compose Python 模块

  • GNU make

  • Git

我们可以通过运行以下 git 命令来克隆 galaxy 存储库,该存储库由 Ansible 维护:

$ git clone https://github.com/ansible/galaxy.git
$ cd galaxy/installer

在 galaxy playbook 中更改所需的变量;默认情况下,它将假定安装在 localhost 上。还要在 inventory 文件中更新密码和其他变量:

然后执行以下命令启动 Ansible playbook 设置以启动本地 Ansible Galaxy

$ ansible-playbook -i inventory galaxy.yml --tags start

这将花费一些时间,因为它必须在本地下载多个 Docker 容器并使用 docker-compose 设置它们之间的集成。

一旦 Playbook 执行完成,我们可以看到有关运行 Docker 容器的以下输出。执行数据库迁移和启动 Web 服务器应用程序仍需要一些时间:

安装完成后,我们可以导航到 http://localhost 查看 web 界面:

请阅读更多关于 Ansible Galaxy 本地设置以及其他身份验证和部署选项的信息,请访问 github.com/ansible/galaxy/blob/develop/INSTALL.md

Ansible 控制器机器安全性

Ansible 控制器机器需要安装和配置 SSH 和 Python。Ansible 的攻击面非常低。在 2017 年 1 月,一家名为 Computest 的公司发现了多个安全问题。

请阅读更多关于他们在 www.computest.nl/advisories/CT-2017-0109_Ansible.txt 发现的信息。

此漏洞被称为“拥有农场”,因为攻击控制器将意味着所有节点可能被攻击。

控制器机器应该是一个经过加固的服务器,并且应该被认真对待。在已经公开的漏洞中,如果一个节点被攻击者利用,攻击者可以利用它来攻击并访问控制器。一旦他们获得访问权限,他们可以扩展他们对控制器管理的所有其他节点的控制。

由于攻击面已经非常有限,我们能做的最好的事情就是确保服务器保持安全和加固。

有两个值得关注和调查的项目:

解释 Ansible 操作系统加固剧本

我们已经看到了多个剧本和指南,用于遵循不同标准在 第七章中,应用程序和网络的安全加固。这可以根据您的环境完全定制,但是遵循某些准则将确保其得到良好的保护。

以下剧本是由 DevSec 创建的 Linux 基线。它涵盖了大多数所需的加固检查,基于多个标准,包括 Ubuntu 安全特性,NSA 安全配置指南,ArchLinux 系统加固等。如果需要,可以通过添加更多任务(或)角色来改进。

Ansible 操作系统加固剧本涵盖

  • 配置软件包管理,即只允许签名软件包

  • 移除已知问题的软件包

  • 配置 pampam_limits 模块

  • Shadow 密码套件配置

  • 配置系统路径权限

  • 通过软限制禁用核心转储

  • 限制 root 登录到系统控制台

  • 设置 SUIDs

  • 通过 sysctl 配置内核参数

以下命令是从 Ansible Galaxy 下载 os-hardening 角色:

$ ansible-galaxy install dev-sec.os-hardening

然后在您的剧本中调用该角色并执行它来执行基线加固,并根据需要更改变量。有关更详细的选项,请参阅galaxy.ansible.com/dev-sec/os-hardening

- hosts: localhost
 become: yes

 roles:
 - dev-sec.os-hardening
$ ansible-playbook main.yml

以下截图是剧本执行的参考,列出了它在 Ansible 控制器机器上执行的一系列检查:

以下是通过更新系统中的配置参数来最小化系统访问的检查:

以下截图是升级密码哈希算法、更新 suid 和超级用户二进制文件指南的参考:

要了解此剧本执行的更多检查,请访问github.com/dev-sec/ansible-os-hardening/blob/master/tasks/main.yml

最佳实践和参考剧本项目

Ansible 强大且灵活。人们以许多不同的方式使用它,了解如何将其用于安全自动化的其中一种方式是追踪并阅读为特定用例创建的 playbooks。

诸如 Algo、DebOps 和 OpenStack 等项目是大型 Ansible playbook 项目,默认情况下受到良好维护和保护。

DebOps – 基于 Debian 的一站式数据中心

DebOps (debops.org) 是由 Maciej Delmanowski 创建的项目。它包含各种用于 Debian 和 Ubuntu 主机的 Ansible playbooks 集合。这个项目有超过 128 个 Ansible 角色,针对生产用例进行了定制,并与多个环境配合使用。

我们可以在 github.com/debops/debops-playbooks 看到可用的 playbooks 服务列表:

设置 DebOps 控制器

我们可以通过两种不同的方式快速开始使用 DebOps 设置:

  • Vagrant 设置

  • Docker 设置

运行以下命令以启动由 DebOps 创建的 Docker 容器:

$ docker run --name debops -it debops/debops

我们可以通过 DebOps playbooks 创建和执行不同的角色来执行不同的操作。请参考主要文档在 docs.debops.org/en/latest/index.html

Algo – 在云中设置个人 IPSEC VPN

Trail of Bits 的 Algo 提供了 Ansible 角色和脚本,以自动化个人 IPSEC VPN 的安装。

通过运行 Ansible playbooks,您可以获得一个完整的加固 VPN 服务器,并且已经配置了所有主要云提供商的部署(github.com/trailofbits/algo/blob/master/docs/deploy-from-ansible.md)。

OpenStack-Ansible

OpenStack-Ansible 是使用 Ansible playbooks 部署和配置 OpenStack 的官方项目。

从这里开始了解 OpenStack-Ansible: github.com/openstack/openstack-ansible

这个项目不仅广泛使用 Ansible playbooks,而且他们的安全文档值得阅读和效仿。最好的部分是所有的安全配置都是在 Ansible playbooks 中以声明性方式编码的安全性。

此项目的文档可在 docs.openstack.org/project-deploy-guide/openstack-ansible/latest/app-security.html 上找到。

其他参考文献

我们在为这本书进行研究时找到的一些很好的关于 Ansible 的在线参考文献和链接有:

  • Streisand:自动安装和配置反审查软件

  • Sovereign:使用 Ansible playbooks 维护您自己的私有云

  • AWX:Ansible Tower 的开源版本

Streisand – 自动安装和配置反审查软件

使用 Ansible playbooks,Streisand 可以设置一个充满软件的云服务器,以规避互联网限制和在线审查。设置的工具包括基于 IPSEC 的 VPN、OpenVPN、OpenConnect、Tor 和 WireGuard。

在这里开始使用 Streisand:github.com/StreisandEffect/streisand.

Sovereign – 使用 Ansible playbooks 维护您自己的私有云

使用 Ansible playbooks,Sovereign 使用开源软件设置了你自己的私有云。这使你能够控制你的数据,服务包括电子邮件、日历、文件同步、RSS 阅读器、Git 托管、稍后阅读和聊天。

在这里开始使用 Sovereign:github.com/sovereign/sovereign.

AWX – Ansible Tower 的开源版本

AWX 提供了基于 web 的用户界面、REST API 和建立在 Ansible 之上的任务引擎。AWX 可以与 tower-CLI 工具和客户端库一起使用。

在这里开始使用 AWX:github.com/ansible/awx.

从这里开始使用 tower-cli:github.com/ansible/tower-cli/.

即将推出的 Ansible 2.5

预计 Ansible 版本 2.5 将于 2018 年 3 月发布。与当前稳定版本 2.4.2 相比,没有主要变化。由于软件世界总是一个不断变化的目标,跟踪可能会发生的变化或不发生的变化的好地方是遵循路线图和移植指南:

概要

在本章中,我们介绍了如何使用 Ansible Vault,在托管的 Ansible Galaxy 网站上使用它,甚至自行托管它。我们还讨论了保持控制节点安全的必要性。

除了这些主题,我们还查看了一些以各种方式使用 Ansible 的最全面的软件项目。在所有这些项目中,Ansible 是它们编排和提供软件及相关服务的核心。突出所有这些项目的主要思想是扩展本书的主题,同时让你了解 Ansible 在自动化领域,特别是在安全工作负载方面的使用方式之多。我们还看了下一年即将发布的 Ansible 2.5 中会有什么内容,并得出结论,即到目前为止,我们介绍的任何内容在它稳定后都不会发生变化。

我们期待着看到在与我们共同走过这段旅程后,大家将构建出怎样的安全自动化工作流。

标签:指南,name,Ansible2,使用,ansible,Ansible,playbook,自动化,我们
From: https://www.cnblogs.com/apachecn/p/18201591

相关文章

  • Django框架指南
    Django框架指南入门安装Django系统安装python后,使用pip安装Djangopipinstalldjango创建一个Django项目在命令行中,使用以下命令创建一个新的Django项目:django-adminstartprojectmyproject这将创建一个名为myproject的文件夹,其中包含了一个Django项目的基本结构。创建......
  • conda使用指南
    Python与Conda:简单、便捷的包管理工具Python作为一门流行的编程语言,在数据分析、机器学习和深度学习等领域得到了广泛应用。然而,Python的库众多,版本繁多,所以在库的安装和版本管理上可能存在困难。为解决这一问题,我们可以借助Conda这一方便易用的包管理工具。安装Anaconda首先......
  • jQuery2-动画技术入门指南-全-
    jQuery2动画技术入门指南(全)原文:zh.annas-archive.org/md5/71BE345FA56C4A075E859338F3DCA6DA译者:飞龙协议:CCBY-NC-SA4.0序言jQuery是一个跨浏览器的JavaScript库,旨在简化HTML的客户端脚本编写,并且是当今最流行的JavaScript库。利用jQuery提供的功能,开发人员能......
  • DockerDesktop安装指南以及Windows下WSL2和 Hyper-V相关问题追查
    文章原创不易,转载请注明来源,谢谢!一、 问题周末在家,给自己的老的台式机安装DockerDesktop。电脑配置是处理器Intel(R)Core(TM)[email protected]  3.30GHz    机带RAM16.0GB(15.9GB可用)    系统类型64位操作系统,基于x64的处理器   ......
  • Ansible自动化运维工具
    目录一、什么是Ansible1、简介2、架构3、工作流程二、部署Ansible批量管理1、涉及主机2、安装部署Ansible2.1、yum安装2.2、其他方式3、设置免密登录3.1、控制节点设置hosts解析3.2、生成密钥对3.3、将公钥发送给受管节点3.4、测试免密登录4、定义主机清单4.1、ansible常见的配置......
  • 大模型_3.2 RAG 高效应用指南
    一、概述 构建一个RAG应用的概念验证过程相对简单,但要将其推广到生产环境中则会面临多方面的挑战。这主要是因为RAG系统涉及多个不同的组件,每个组件都需要精心设计和优化,以确保整体性能达到令人满意的水平。在这一过程中,外部非结构化数据的清洗和处理、文本分块、Query的......
  • 班味培养指南
    班味养成指南前言旨在帮助社团的同学找到实习、工作,默认具备一定的游戏制作能力,熟练使用至少一款游戏引擎,语言基础较好,计算机知识掌握较为全面(如计算机网络、操作系统等)分三个大方向进行分享,我愿称之为将来时、现在进行时、现在完成时将来时是指找工作之前要准备的内容,比如......
  • 一文彻底整明白,基于Ollama工具的LLM大语言模型Web可视化对话机器人部署指南
    在上一篇博文中,我们在本地部署了Llama38B参数大模型,并用Python写了一个控制台对话客户端,基本能愉快的与Llama大模型对话聊天了。但控制台总归太技术化,体验不是很友好,我们希望能有个类似ChatGPT那样的Web聊天对话界面,本博文就安排起来……上一篇Llama38B大模型部署......
  • Angular2-切换指南-全-
    Angular2切换指南(全)原文:zh.annas-archive.org/md5/AE0A0B893569467A0AAE20A9EA07809D译者:飞龙协议:CCBY-NC-SA4.0前言AngularJS是一个使构建Web应用程序更容易的JavaScript开发框架。它如今被用于大规模、高流量的网站,这些网站在性能不佳、可移植性问题、SEO不友好......
  • Windows Security Baselines(安全基线指南) 是由微软提供的一个安全配置集合,旨在帮助组
    安全基线指南-WindowsSecurity|MicrosoftLearnWindowsSecurityBaselines(安全基线)是由微软提供的一个安全配置集合,旨在帮助组织和管理员快速部署一套推荐的安全设置,以增强Windows操作系统及其组件的安全性。这些基线覆盖了操作系统本身、MicrosoftEdge浏览器、Inter......