0


Hadoop 安全实践指南(一)

原文:Practical Hadoop security

协议:CC BY-NC-SA 4.0

零、简介

去年,我为一个客户设计安全性,他正在寻找一本关于 Hadoop 领域安全性实现的参考书,这样他就可以避免已知的问题和陷阱。令我懊恼的是,我找不到一本详细介绍 Hadoop 安全方面的书,也找不到一本为打算保护存储敏感数据的集群的人提供选择的书。我既失望又惊讶。每个计划保护其 Hadoop 集群的人肯定都经历过类似的挫折。所以我决定将我的安全设计经验应用到更广泛的领域,并自己写这本书。

随着 Hadoop 日益获得更多的公司支持和使用,我们都需要认识并关注 Hadoop 的安全方面。企业实现还涉及遵循数据保护和机密性的法规和法律,这些安全问题是使 Hadoop“企业就绪”的驱动力

开源软件通常缺乏有组织的文档和关于独特执行特定功能任务的共识,Hadoop 在这方面也不例外。过去几年中涌现的各种发行版在实现各种 Hadoop 功能方面有所不同,有些功能,如授权或加密,甚至不是所有的供应商发行版都提供的。所以,在这方面,Hadoop 就像 80 年代或 90 年代的 Unix:开源开发导致了大量的变化,在某些情况下偏离了功能。由于这些变化,设计一个通用策略来保护您的 Hadoop 安装是很困难的。在本书中,我试图提供一个适用于大多数情况的策略和解决方案(可能的话是开源解决方案),但也可能存在例外,尤其是如果您使用的是不太知名的 Hadoop 发行版。

开发这本书是一个伟大而激动人心的旅程,我故意说“开发”,因为我相信创作一本技术书籍非常类似于从事一个软件项目。有挑战,有回报,有令人兴奋的发展,当然,还有不可预见的障碍——更不用说最后期限了!

这本书是给谁的

对于计划生产 Hadoop 环境的 IT 经理或想要保护其环境的 Hadoop 管理员来说,这本书是一个极好的资源。这本书也适用于希望在其环境中实现安全性的 Hadoop 开发人员,以及希望了解 Hadoop 安全性的学生。本书假设读者对 Hadoop(尽管第一章回顾了许多基本概念)、Kerberos、关系数据库和 Hive 有基本的了解,并对 Linux 有中级的了解。

这本书的结构

本书分为五个部分:第一部分,“Hadoop 及其安全性介绍”,包含第一章、第二章和第三章;第二部分“在您的 Hadoop 集群中进行认证和授权”,横跨第四章和第五章;第三部分“审计日志和安全监控”,包含第六章和第七章;第四部分,“Hadoop 加密”,包含第八章;第五部分包含四个附录。

以下是每一章更详细的预览:

  • 第一章“理解安全概念”概述了安全、安全工程框架、安全协议(包括 Kerberos)和可能的安全攻击。本章还解释了如何保护分布式系统,并以 Microsoft SQL Server 为例讨论了安全系统。
  • 第二章“Hadoop 简介”,介绍了 Hadoop 架构和 Hadoop 分布式文件系统(HDFS),并解释了 HDFS 固有的安全问题以及为什么很容易侵入 HDFS 安装。还介绍了 Hadoop 的 MapReduce 框架,并讨论了它的安全性缺点。最后,它讨论了 Hadoop 堆栈。
  • 第三章“Hadoop 安全性简介”是为 Hadoop 设计和实现安全性的技术路线图。它引入了认证(使用 Kerberos)来提供安全的访问、授权来指定访问级别,以及监控未授权的访问或不可预见的恶意攻击(使用 Ganglia 或 Nagios 等工具)。您还将了解记录对 Hadoop 守护进程的所有访问的重要性(使用 Log4j 日志记录系统)以及数据加密的重要性(传输中和静态)。
  • 第四章“Hadoop 中的开源认证”,讨论如何使用开源解决方案保护您的 Hadoop 集群。它从使用 PuTTY 保护客户端开始,然后描述 Kerberos 架构,并一步一步地详细介绍 Hadoop 的 Kerberos 实现。此外,您将学习如何保护使用 RPC(远程过程调用)协议的进程间通信,如何加密 HTTP 通信,以及如何保护使用 DTP(数据传输协议)的数据通信。
  • 第五章“实现细粒度授权”,从确定安全需求的方法(基于应用程序)开始,然后研究为应用程序设计细粒度授权的方法。目录级和文件级权限用一个真实的例子来演示,然后用 HDFS 访问控制列表和 Apache Sentry with Hive 来重新实现同一个例子。
  • 第六章“Hadoop 日志:关联和解释”,讨论了日志记录的安全性使用。在对 Log4j API 以及如何使用它进行审计日志记录进行了高级讨论之后,本章将研究 Log4j 日志记录级别及其用途。您将了解如何关联 Hadoop 日志以有效实现安全性,了解 Hadoop 分析以及使用 Splunk 的可能实现。
  • 第七章“Hadoop 中的监控”讨论了安全监控。它首先讨论监控系统需要的特性,重点是监控分布式集群。此后,本文讨论了可以用于安全目的的 Hadoop 指标,并研究了 Ganglia 和 Nagios 的使用,这是两个最流行的 Hadoop 监控应用程序。本文最后讨论了一些对 Ganglia 和 Nagios 有用的插件,这些插件提供了与安全性相关的功能,还讨论了 Ganglia 与 Nagios 的集成。
  • 第八章“Hadoop 中的加密”从一些数据加密基础知识开始,讨论了流行的加密算法及其应用(证书、密钥、哈希函数、数字签名),定义了 Hadoop 集群可以加密的内容,并列出了一些流行的加密供应商选项。下面是 HDFS 和 Hive 静态数据的详细实现,展示了英特尔的实际分布。本章以使用 Amazon Web Services 的 Elastic MapReduce VM (EMR)逐步实现静态加密作为结束。

下载代码

这本书的源代码可以在 Apress 网站的下载部分获得。

联系作者

您可以在

[email protected]

[email protected]

到达 Bhushan Lakhe。

一、理解安全概念

在当今技术驱动的世界中,计算机已经渗透到我们生活的各个方面,我们的个人和公司数据比以往任何时候都更容易通过电子方式获得。不幸的是,提供如此多好处的同一技术也可能被用于破坏性目的。近年来,以前主要为个人利益而工作的个人黑客组织成了为经济利益而工作的团体,使得个人或公司数据被窃取用于非法目的的威胁变得更加严重和真实。恶意软件侵扰我们的计算机,并根据我们的浏览环境将我们的浏览器重定向到特定的广告网站。网络钓鱼邮件诱使我们登录看似真实但旨在窃取我们密码的网站。病毒或直接攻击破坏我们的网络,窃取密码和数据。随着大数据、分析和机器学习进入现代企业,暴露关键数据和造成伤害的机会呈指数级增长。

如果您想应对这些针对您个人财产(是的,您的数据是您的个人财产)或公司财产的攻击,您必须彻底了解这些威胁以及您自己的漏洞。只有这样,您才能设计一种策略来保护您的数据,无论是个人数据还是公司数据。

想象一下这样一个场景,您银行的投资部门使用 Hadoop 来分析万亿字节的数据,而您银行的竞争对手可以访问结果。或者,如果您的保险公司基于对数百万份索赔的大数据分析决定停止提供房主保险,而他们的竞争对手已经(秘密地)访问了这些数据,并发现用作分析基础的大部分索赔都是欺诈性的,情况会如何?你能想象这些安全漏洞会给受影响的公司带来多大的损失吗?不幸的是,只有这些漏洞凸显了安全的重要性。对于用户来说,一个好的安全设置——无论是个人的还是公司的——总是透明的。

本章为您开始构建安全策略奠定了基础。我首先定义一个安全工程框架。然后,我讨论了安全的一些心理学方面(人的因素),并介绍了安全协议。最后,我介绍了对程序安全性的常见潜在威胁,并解释了如何应对这些威胁,提供了一个安全分布式系统的详细示例。首先,让我向您介绍一下安全工程的概念。

安全工程简介

安全工程是关于设计和实现不泄露私人信息的系统,并且能够可靠地抵御恶意攻击、错误或灾难。作为一门科学,它专注于设计和实现完整系统以及改造现有系统所需的工具、过程和方法。

安全工程需要跨不同学科的专业知识,如密码学、计算机安全、计算机网络、经济学、应用心理学和法律。软件工程技能(从业务流程分析到实现和测试)也是必要的,但主要是为了应对错误和“灾难”——而不是恶意攻击。设计对抗恶意的系统需要专门的技能,当然也需要专门的经验。

安全要求因系统而异。通常您需要用户认证、授权、策略定义、审计、集成事务、容错、加密和隔离的平衡组合。许多系统失败是因为他们的设计者关注了错误的事情,忽略了其中的一些因素,或者关注了正确的事情但做得不充分。保护包含许多组件和接口的大数据系统尤其具有挑战性。传统的数据库只有一个目录和一个接口:SQL 连接。一个 Hadoop 系统有许多“目录”和许多接口(Hadoop 分布式文件系统或 HDFS、Hive、HBase)。这种日益增加的复杂性,以及此类系统中各种各样的海量数据,给安全工程师带来了许多挑战。

因此,保护系统取决于几种类型的过程。首先,您需要确定您的安全需求,然后如何实现它们。此外,您必须记住,安全系统除了技术组件之外,还有一个非常重要的组件:人的因素!这就是为什么你必须确保负责保护和维护系统的人有适当的动力。在下一节中,我定义了一个考虑所有这些因素的框架。

安全工程框架

良好的安全工程依赖于以下五个在系统概念化时需要考虑的因素:

  • 策略:你的策略围绕着你的目标。一个具体的目标是为您的系统定义认证、授权、整体事务、容错、加密和隔离的良好起点。您还需要考虑可能的错误条件或恶意攻击场景。
  • **实现:**实现您的战略包括采购必要的硬件和软件组件,设计和开发满足您所有目标的系统,定义访问控制,并彻底测试您的系统以匹配您的战略。
  • **可靠性:**可靠性是你对你的每个系统组件以及整个系统的依赖程度。可靠性是根据故障和失灵来衡量的。
  • **相关性:**相关性决定系统抵御最新威胁的能力。为了保持相关性,尤其是对于安全系统,定期更新它以保持其应对新威胁的能力也是极其重要的。
  • **动机:**动机与负责管理和维护您的系统的人员正确完成工作的动力或奉献精神有关,也指攻击者试图挫败您的策略的诱惑。

图 1-1 说明了这五个因素是如何相互作用的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1-1 。设计安全框架前需要考虑的五个因素

注意这些关系,比如相关性的策略、策略的实现、相关性的实现、动机的可靠性等等。

通过一个真实世界的例子来考虑图 1-1 的框架。假设我正在设计一个存储高中生成绩的系统。这五个关键因素是如何发挥作用的?

带着我的目标——创建一个学生评分系统——我首先概述了这个系统的策略。首先,我必须定义学生、员工和学校管理员所需的认证和授权级别(访问策略)。显然,学生只需要对他们的个人成绩有读取权限,工作人员需要对他们学生的成绩有读写权限,学校管理员需要对所有学生记录有读取权限。任何数据更新都需要是一个整体事务,这意味着要么它应该完成所有相关的更改,要么如果它在进行中中止,那么所有的更改都应该恢复。因为数据是敏感的,所以应该加密——学生应该只能看到自己的成绩。应该使用内部防火墙将评分系统隔离在学校内部网中,并且当任何人试图使用该系统时,应该提示进行认证。

我的策略需要通过首先采购必要的硬件(服务器、网卡)和软件组件(SQL Server、C#)来实现。NET 组件、Java)。接下来是通过使用 SQL Server 设计过程流、数据流、逻辑数据模型、物理数据模型以及使用 Java 设计图形用户界面来设计和开发系统以满足目标。我还需要定义访问控制,以确定谁可以访问系统以及拥有什么权限(基于授权需求的角色)。例如,我将

School_Admin

角色定义为具有所有等级的读取权限,将

Staff

角色定义为具有读写权限,以此类推。最后,在构建系统之前,我需要对我的硬件和软件组件进行安全实践审查。

在彻底测试系统时,我可以通过确保没有人可以访问他们不应该访问的数据,以及确保所有用户都可以访问他们被允许访问的数据来测量可靠性。任何偏离这一功能的情况都会使系统不可靠。此外,系统需要全天候可用。如果不是,那也会降低系统的可靠性。这个系统的相关性将取决于它的固若金汤。换句话说,任何学生(或外部黑客)都不能使用任何最新的技术侵入它。

负责管理该系统(硬件、数据库等)的系统管理员。)应该是可靠的并且有动力有良好的职业操守。既然他们可以接触到所有的敏感数据,他们就不应该向任何未经授权的人透露(例如在该高中学习的朋友或亲戚,任何无良的招生人员,甚至媒体)。在这种情况下,禁止任何此类披露的法律可能是一个很好的动机;但是职业操守同样重要。

安全工程的心理学方面

为什么需要了解安全工程的心理学方面?对你的网络安全最大的威胁是欺骗:利用心理学和技术的恶意攻击。我们都收到过网络钓鱼电子邮件,警告我们支票、信用卡或 PayPal 账户存在一些“问题”,并敦促我们通过登录一个巧妙伪装的网站来“修复”它,该网站旨在出于非法目的捕获我们的用户名、密码或账号。借口是私家侦探或骗子窃取信息的另一种常见方式,无论是个人信息还是公司信息。它包括以虚假的借口给某人(掌握信息的受害者)打电话,并获取机密信息(通常是通过伪装成有权获得该信息的人)。开发人员或系统管理员接到“安全管理员”打来的电话,被要求提供密码信息,据说是为了验证或安全目的,这种情况有很多。你可能会认为这在今天是行不通的,但是这些情况即使在现在也很常见!最好通过电子邮件或书面形式请求披露任何机密或敏感信息。

公司使用许多对策来打击网络钓鱼:

  • **密码加扰器:**许多浏览器插件通过散列(使用秘密密钥)和被访问网站的域名,将你的密码加密成一个强大的、特定域的密码。即使您总是使用相同的密码,您访问的每个网站都会有一个不同的、唯一的密码。因此,如果你在一个钓鱼网站上错误地输入了你的美国银行密码,黑客就会得到你真实密码的一个不可用的变体。
  • **客户证书或定制应用:**一些银行提供自己的笔记本电脑和 VPN 接入,以便使用他们的定制应用连接到他们的系统。他们验证客户端是否使用了他们自己的硬件(例如,通过媒体访问控制或 MAC 地址),并在允许用户连接到他们的系统之前使用 VPN 凭证来验证用户。一些银行还向他们的用户提供由他们的服务器认证的客户证书;因为它们驻留在客户端电脑上,黑客无法访问或使用它们。
  • **两阶段认证:**在该系统中,登录需要令牌密码和保存密码。安全令牌生成密码(一次性使用或基于时间)以响应您要访问的系统发送的质询。例如,每隔几秒钟,安全令牌就会显示一个与中央服务器同步的新的八位密码。输入令牌密码后,系统会提示您输入之前设置的已保存密码。这使得黑客无法使用您的密码,因为令牌密码变化太快,黑客无法使用。两阶段认证仍然容易受到实时“中间人”攻击(有关更多详细信息,请参见“中间人攻击”侧栏)。

中间人攻击

中间人攻击的工作原理是,黑客成为合法用户和验证者之间的隐形中继(中间人),以获取非法使用的信息。黑客(或“网络钓鱼者”)捕获用户响应,并将它们转发给验证者。然后,他或她将来自认证者的任何质询转发给用户,并将任何后续的用户响应转发给认证者。因为所有的响应都通过黑客,所以他被认证为一个用户,而不是真正的用户,因此可以冒充合法用户自由地执行任何非法活动!

例如,假设一个用户想要登录他的支票账户,但是被一个网络钓鱼计划引诱而登录到一个网络钓鱼站点。网络钓鱼网站同时开启与用户银行的登录会话。当银行发送挑战时;钓鱼者将此转发给用户,用户使用他的设备对其进行响应;网络钓鱼者将此响应转发给银行,并且现在作为用户向银行进行了认证!当然,在那之后,他可以在那个支票账户上进行任何非法活动,比如把所有的钱转到他自己的账户上。

一些银行通过使用基于最后提取金额、收款人账号或交易序列号的认证代码作为响应,而不是简单的响应,来应对这种情况。

  • **可信计算:**这种方法包括在 PC 主板上安装 TPM(可信平台模块)安全芯片。TPM 是一个专用的微处理器,它生成密钥并使用它们进行加密/解密。因为本地化的硬件用于加密,所以它比软件解决方案更安全。为了防止任何恶意代码获取和使用密钥,您需要确保整个加密/解密过程都在 TPM 内完成,而不是由 TPM 生成密钥并将它们传递给外部程序。将这种硬件交易支持集成到 PC 中将使黑客更难侵入系统。例如,OpenSSL 中最近出现的 Heartbleed 错误将被 TPM 击败,因为密钥不会暴露在系统内存中,因此不会被泄漏。
  • 强密码协议:史蒂夫·贝洛文和迈克尔·梅里特提出了一系列用于加密密钥交换的协议,通过这种方式,密钥交换与共享密码结合在一起,使得中间人(phisherman)无法猜出密码。其他各种研究人员提出了类似的协议,这项技术是我们今天使用的“安全”(HTTPS)协议的前身。因为使用 HTTPS 更方便,所以它被广泛地实现,而不是现在的浏览器都没有实现的强密码协议。
  • **双通道认证:**这包括通过单独的通道或设备(如用户的手机)向用户发送一次性访问码。此访问码与常规用户密码一起用作附加密码。这种认证类似于两阶段认证,也容易受到实时中间人攻击。

安全协议简介

安全系统由用户、公司和服务器等组件组成,这些组件使用包括电话、卫星链路和网络在内的多种渠道进行通信,同时还使用物理设备,如笔记本电脑、便携式 USB 驱动器等。安全协议是管理这些通信的规则,旨在有效对抗恶意攻击。

由于实际上不可能设计一个协议来对抗所有类型的威胁(除了昂贵之外),协议被设计成仅对抗某些类型的威胁。例如,用于认证的 Kerberos 协议假设用户在输入用户名和密码时连接到了正确的服务器(而不是钓鱼网站)。

对协议进行评估时,通常会考虑它们所要应对的威胁出现的可能性,以及它们消除这种威胁的有效性。

在一个庞大而复杂的系统中,多种协议常常必须协同工作;因此,您需要注意这种组合不会暴露任何漏洞。在接下来的几节中,我将向您介绍一些常用的协议。

Needham-Schroeder 对称密钥协议

Needham-Schroeder 对称密钥协议在请求者和认证者之间建立了一个会话密钥,并在整个会话中使用该密钥来确保通信的安全。让我用一个简单的例子来解释一下。

用户需要从安全文件系统访问文件。作为第一步,用户通过提供她的 nonce (用于保证消息新鲜的随机数或序列号)和她需要访问的安全文件系统的名称,向认证服务器请求会话密钥(图 1-2 中的步骤 1)。服务器提供会话密钥,使用服务器和用户之间共享的密钥进行加密。会话密钥还包含用户的 nonce,只是为了确认它不是重播。最后,服务器向用户提供使用服务器和安全文件系统之间共享的密钥加密的会话密钥的副本(步骤 2)。用户将密钥转发给安全文件系统,安全文件系统可以使用与服务器共享的密钥对其进行解密,从而认证会话密钥(步骤 3)。安全文件系统向用户发送使用会话密钥加密的随机数,以表明它拥有该密钥(步骤 4)。用户在 nonce 上执行一个简单的操作,重新加密它,并将其发送回来,验证她仍然活着,并且她持有密钥。因此,在用户和安全文件系统之间建立了安全通信。

这个协议的问题是,安全文件系统必须假设它从认证服务器(通过用户)接收的密钥是新的。这可能不是真的。此外,如果黑客得到了用户的密钥,他可以用它与许多其他主体建立会话密钥。最后,如果用户通过使用日志发现冒名顶替或不当使用,她不可能撤销会话密钥。

总之,Needham-Schroeder 协议容易受到重放攻击,因为不可能确定会话密钥是新的还是最近的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1-2 。Needham-Schroeder 对称密钥协议

麻省理工学院开发的安全认证系统

Kerberos 是 Needham-Schroeder 协议的衍生物,起源于麻省理工学院,现在被用作 Linux 和 Windows 的标准认证工具。Kerberos 不是使用单个可信服务器,而是使用两个服务器:一个认证服务器,对用户登录进行认证;以及提供票证的票证授予服务器,允许访问各种资源(例如,文件或安全进程)。这提供了更具可伸缩性的访问管理。

如果用户需要访问使用 Kerberos 的安全文件系统,该怎么办?首先,用户使用密码登录到认证服务器。用户 PC 上的客户端软件从该服务器获取票证,该票证根据用户的密码进行加密,并包含会话密钥(仅在预定的持续时间内有效,如一小时或一天)。假设用户已经过认证,他现在使用会话密钥来访问由票据授予服务器控制的安全文件系统。

接下来,用户从票据授予服务器请求访问安全文件系统。如果访问是允许的(取决于用户的权限),则创建一个包含合适密钥的票证并提供给用户。用户还可以获得在会话密钥下加密的密钥的副本。现在,用户通过向安全文件系统发送时间戳来验证票据,安全文件系统通过发回加 1 的时间戳来确认票据是否有效(这表明它能够正确解密票据并提取密钥)。之后,用户可以与安全文件系统通信。

Kerberos 通过用时间戳替换随机随机数来修复 Needham–Schroeder 的漏洞。当然,现在有一个基于时间戳的新漏洞,在这个漏洞中,作为更复杂攻击的一部分,各种客户端和服务器上的时钟可能会故意失去同步。

Kerberos 被广泛使用,并作为其认证机制被集成到 Windows Active Directory 服务器中。实际上,Kerberos 是使用最广泛的安全协议,其他协议只具有历史重要性。您将在后面的章节中了解更多关于 Kerberos 的内容,因为它是当今 Hadoop 使用的主要认证。

布伦斯-阿巴迪-李约瑟逻辑

burrows-Abadi-Needham(BAN)逻辑提供了定义和分析敏感信息的框架。基本原则是,如果消息满足三个标准,则它是可信的:它用相关密钥加密,它来自可信的来源,并且它还是新的(即,在协议的当前运行期间生成)。通常遵循的验证步骤是

  1. 检查来源是否可信,
  2. 检查加密密钥是否有效,以及
  3. 检查时间戳以确保它是最近生成的。

一些银行使用 BAN 逻辑的变体(例如,Visa International 使用的 COPAC 系统)。BAN 逻辑是一个非常广泛的协议,因为它有多步验证过程;但这也是它不太受欢迎的确切原因。它实现起来很复杂,也容易受到时间戳操作的影响(就像 Kerberos 一样)。

考虑 BAN 逻辑的实际实现。假设 Mindy 从网络零售商处购买了一个昂贵的钱包,并授权通过她的信用卡向零售商支付 400 美元。Mindy 的信用卡公司必须能够核实和证明该请求确实来自 Mindy,如果她后来否认发送它。信用卡公司还想知道这个请求完全是 Mindy 的,并且没有被修改过。此外,该公司必须能够验证 Mindy 输入的加密密钥(来自信用卡的三位数安全码)。最后,公司希望确保消息是新的,而不是重复使用以前的消息。所以,查看需求,您可以得出结论,信用卡公司需要实现 BAN 逻辑。

现在,在回顾了这些协议以及它们可以用来对抗恶意攻击的方式之后,您认为使用一个强大的安全协议(来保护程序)足以克服软件中的任何“缺陷”(这些缺陷会使程序容易受到安全攻击)吗?还是像用一把昂贵的锁锁住房子的前门,而让窗户开着?要回答这个问题,您首先需要知道缺陷是什么,或者它们如何导致安全问题。

保护程序安全

在保护程序之前,您需要了解是什么因素使程序不安全。首先,使用安全协议只能保护程序的入口。一旦程序开始执行,它需要具有健壮的逻辑,只提供对必要资源的访问,而不为恶意攻击提供任何途径来修改系统资源或获得对系统的控制。那么,这就是一个程序没有缺陷的方式吗?好吧,我将简单地讨论一下,但是首先让我定义一些重要的术语,这将帮助你理解缺陷以及如何应对它们。

先说术语程序??。程序是任何可执行的代码。甚至操作系统或者数据库系统都是程序。我认为一个程序是安全的,如果它确切地(并且仅仅)做了它应该做的事情——没有别的!安全性评估也可以基于程序对规范的符合性来决定——如果代码满足安全性要求,那么它就是安全的。为什么这很重要?因为当一个程序执行时,它有能力修改你的环境,你必须确保它只修改你想让它修改的。

因此,您需要考虑会阻止程序满足安全性要求的因素。这些因素有可能被称为程序中的缺陷。瑕疵可以是错误,也可以是失败

故障是由于人为错误在系统中引入的异常。在设计阶段,由于设计者误解了分析师的需求,或者在实现阶段,由于程序员没有理解设计者的意图并且编码不正确,可能会引入错误。一个错误可以产生许多错误。综上所述,故障是系统的设计者或开发者在开发之后注意到的逻辑问题或矛盾。

一个失败是对系统所需功能的偏离。故障可以在软件开发生命周期(SDLC)的任何阶段被发现,例如测试或运行。单个故障可能导致多个故障(例如,如果没有输入,设计故障会导致程序退出)。如果功能需求文档包含错误,失败将表明系统没有按要求执行(即使它可能按指定执行)。因此,失败是故障的明显后果:用户可以看到的问题。

幸运的是,不是每个错误都会导致失败。例如,如果代码的错误部分从未被执行,或者逻辑的错误部分从未被输入,那么该错误将永远不会导致代码失败——尽管您永远无法确定失败何时会暴露该错误!

概括地说,这些缺陷可以分为:

  • 非恶意(缓冲区溢出、验证错误等。)和
  • 恶意(病毒/蠕虫攻击、恶意软件等。).

在接下来的几节中,我们将更仔细地研究这些缺陷、它们可能产生的安全漏洞的种类,以及如何设计一种策略来更好地保护您的软件免受此类漏洞的侵害。

非恶意缺陷

非恶意缺陷源于无意的、疏忽的人为错误。大多数这些缺陷只会导致程序故障。然而,最近几年,一些类别已经导致了许多安全漏洞。

缓冲区溢出

一个缓冲区(或数组字符串)是一个分配的内存(或 RAM)量,数据在这里被临时保存以供处理。如果写入缓冲区的程序数据超过缓冲区先前定义的最大大小,则该程序数据基本上溢出缓冲区。一些编译器检测到缓冲区溢出并停止程序,而另一些则简单地认为溢出是附加指令并继续执行。如果继续执行,程序数据可能会覆盖系统数据(因为所有程序和数据元素在执行期间都与操作系统和其他代码共享内存空间)。黑客可能会发现溢出并在系统空间中插入代码,从而以更高的权限控制操作系统。 1

有几种编程技术用于防止缓冲区溢出,例如

  • 强制检查缓冲区溢出;
  • 系统堆栈区和用户代码区的分离;
  • 使内存页面可写或可执行,但不能两者都写;和
  • 监视器在系统堆栈被覆盖时发出警报。

不完全调解

当程序未经验证或确认就接受用户数据时,就会发生不完全中介。程序需要检查用户数据是否在指定的范围内,或者是否遵循预定义的格式。如果没有做到这一点,黑客就可以出于非法目的操纵数据。例如,如果一个网络商店不传递用户数据,黑客可能会关闭任何客户端 JavaScript(用于验证)或只编写一个脚本来与网络服务器交互(而不是使用网络浏览器),并向服务器发送任意(非中介)值来操纵销售。在某些情况下,这种性质的漏洞是由于未能检查组件的默认配置造成的;默认情况下为 XML 数据启用 shell 转义的 web 服务器就是一个很好的例子。

不完全中介的另一个例子是 SQL 注入,攻击者能够插入(和提交)由 web 应用程序执行的数据库 SQL 命令(代替或与参数值一起),操纵后端数据库。当 web 应用程序未经彻底验证就接受用户提供的输入数据时,就会发生 SQL 注入攻击。巧妙格式化的用户数据欺骗应用程序执行非预期的命令或修改敏感数据的权限。黑客可以访问敏感信息,如社会安全号、信用卡号或其他财务数据。

SQL 注入的一个例子是一个 web 应用程序,它接受登录名作为输入数据,并为用户显示所有信息,但不验证输入。假设 web 应用程序使用以下查询:

"SELECT * FROM logins WHERE name ='"+ LoginName +"';"

恶意用户可以使用

“' or '1'='1”

LoginName

值,这将导致 web 应用程序将所有用户的登录信息(带密码)返回给恶意用户。

如果用户输入根据一组定义的长度、类型和语法规则进行验证,就可以防止 SQL 注入。此外,重要的是要确保用户权限(数据库访问)应限制在尽可能低的权限内(仅在相关数据库内),并且系统管理员帐户(如

sa

)不应用于 web 应用程序。不使用的存储过程应该删除,因为它们很容易成为数据操作的目标。

应该采取两个关键步骤进行防御:

  • 必须执行基于服务器的中介。所有客户端输入在被处理之前都需要经过程序(位于服务器上)的验证。
  • 需要检查客户端输入的范围有效性(例如,月份在一月和十二月之间)以及允许的大小(文本数据的字符数或数字数据的数值等)。).

检验时间到使用时间误差

当系统状态(或用户控制的数据)在特定任务的授权检查和任务执行之间发生变化时,检查时间到使用时间的错误就会发生。也就是说,在任务的授权和执行之间缺乏同步或串行化。例如,用户可以请求对无害日志文件的修改权限,并且在检查授权(针对此操作)和实际授予修改权限之间,可以将日志文件切换为关键系统文件(例如,

/etc/password

针对 Linux 操作系统)。

有几种方法可以消除这些错误:

  • 将所请求的用户数据(对于请求)复制到系统区域,使修改变得不可能。
  • 锁定请求数据,直到请求的操作完成。
  • 对请求的数据执行校验和(使用验证程序)以检测修改。

恶意缺陷

恶意缺陷会在程序中产生意想不到的或不希望的影响,并且是故意设计来造成损害(数据损坏、系统崩溃等)的代码的结果。).恶意缺陷是由病毒、蠕虫、兔子、特洛伊木马、陷阱门和恶意软件引起的:

  • 病毒是一种自我复制程序,它可以通过将恶意代码的副本附加到未被感染的程序上来修改这些程序。被感染的程序自己变成病毒,并进一步复制以感染整个系统。一个短暂病毒依赖于它的宿主程序(它是其中的一部分的可执行程序),并且当它的宿主执行时运行,传播它自己并且执行它被设计的恶意活动。一个常驻病毒驻留在系统内存中,可以作为独立程序执行,甚至在其宿主程序完成执行之后。
  • 一个蠕虫不同于使用其他程序作为媒介来传播自己的病毒,它是一个独立的程序,通过网络进行复制。 *** 一只兔子是一种病毒或蠕虫,它可以无限制地自我复制,耗尽计算资源。例如,一只兔子可能会无限次地将自己复制到一个磁盘上,并填满整个磁盘。* 一个特洛伊木马是代码,除了它的主要目的之外,还有隐藏的恶意目的。* 一个逻辑触发器是在特定条件发生时执行的恶意代码(例如,当文件被访问时)。时间触发器是以特定时间或日期为激活条件的逻辑触发器。* 一个陷阱门是一个程序的秘密入口点,它可以让某人绕过正常的认证并获得访问权。活板门一直被程序员用于合法的目的,比如故障排除、调试或测试程序;但是,当不道德的程序员使用它们来获得未经授权的访问或执行恶意活动时,它们就会成为威胁。恶意软件可以在联网的电脑上安装恶意程序或陷阱门。一旦安装,陷阱门就可以打开互联网端口,进行匿名、恶意的数据收集,推销产品(广告软件),或执行创建者设计的任何其他破坏性任务。**

**我们如何防止恶意代码的感染?

  • 仅安装从可靠、知名的供应商处获得的商业软件。
  • 跟踪所有已安装的开源组件的版本和漏洞,并维护开源组件安全修补策略。
  • 仔细检查任何已安装软件的所有默认配置;不要假定默认值是为安全操作而设置的。
  • 孤立地测试任何新软件。
  • 只打开来自已知来源的“安全”附件。此外,避免打开来自已知来源的包含奇怪或特殊邮件的附件。
  • 每天或每周维护一个可恢复的系统映像(根据需要)。
  • 制作并保留可执行系统文件以及可能包含“可感染”代码的重要个人数据的备份副本。
  • 使用防病毒程序并根据需要安排每日或每周扫描。不要忘记更新病毒定义文件,因为每天都有大量新病毒产生!

保护分布式系统

到目前为止,我们已经检查了对 程序的安全性的潜在威胁,但是记住——分布式系统也是一个程序。上一节讨论的所有威胁和解决方案不仅适用于分布式系统,而且这些程序的特殊性质也使它们在其他方面容易受到攻击。这导致分布式系统需要多级安全性。

当我想到一个安全的分布式系统时,我会想到 SAP 或 PeopleSoft 等 ERP(企业资源)系统。此外,Oracle、Microsoft SQL Server 或 Sybase 等关系数据库系统是安全系统的良好范例。所有这些系统都配备了多层安全措施,并且已经运行了很长时间。随后,他们发现了许多针对存储数据的恶意攻击,并设计了有效的对策。为了更好地理解是什么使这些系统安全,我将讨论 Microsoft SQL Server 如何保护敏感的雇员工资数据。

对于一个安全的分布式系统,数据隐藏在多层防御之后(图 1-3 )。存在诸如认证(使用登录名/密码)、授权(具有一组权限的角色)、加密(使用密钥对数据进行加密)等级别。对于 SQL Server,第一层是用户认证层。其次是授权检查,以确保用户拥有通过数据库角色访问数据库的必要授权。具体来说,任何到 SQL Server 的连接都由服务器根据存储的凭据进行认证。如果认证成功,服务器会传递连接。连接后,客户端将继承系统管理员分配给已连接登录的授权。这种授权包括使用分配的角色(对于每个数据库)访问任何系统或用户数据库。也就是说,用户只能访问他有权访问的数据库——并且只能访问分配了权限的表。在数据库级别,安全性进一步划分为表级和列级安全性。必要时,视图被设计成进一步隔离数据并提供更详细的安全级别。数据库角色用于对一组表的安全设置进行分组。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1-3 。SQL Server 通过多种安全级别保护数据

在图 1-3 中,经过认证并被允许连接的用户被授权查看 DB1 数据库中的员工数据,但工资数据除外(因为他不属于 HR 角色,只有人力资源部的用户被分配了 HR 角色)。因此,使用 SQL Server 中的角色可以很容易地限制对敏感数据的访问。虽然图中没有说明它们,但是更多的安全层是可能的,您将在接下来的几节中了解到。

证明

第一层安全是认证。 SQL Server 使用登录/密码对来验证存储的凭据元数据。您还可以将集成安全性用于 Windows,并且可以使用 Windows 登录来连接到 SQL Server(假设系统管理员已经提供了对该登录的访问权限)。最后,证书或一对非对称密钥可用于认证。提供了一些有用的功能,如密码策略实现(强密码)、登录的日期有效性、阻止登录的能力等,以增加便利性。

批准

第二层是授权。根据需要在各种数据库(服务器上)内创建第一层登录对应的用户来实现。如果用户不存在于数据库中,他或她就不能访问它。

在数据库中,有各种对象,如表(保存数据)、视图(对可能分布在多个表中的过滤数据库访问的定义)、存储过程(使用数据库脚本语言的脚本)和触发器(在事件发生时执行的脚本,如更新表中的列或插入表中的数据行),用户可能具有对这些对象的读取、修改或执行权限。此外,对于表或视图,可以向用户提供部分数据访问权限(仅针对某些列)。这在配置访问时提供了灵活性和非常高的粒度。

加密

第三个安全层是加密。SQL Server 提供了两种加密数据的方法:对称密钥/证书和透明数据库加密(TDE)。这两种方法都是对存储在数据库中的“静态”数据进行加密。通过在服务器和客户端上配置相应的公共和私有证书以使用加密连接,SQL Server 还能够对从客户端传输到服务器的数据进行加密。仔细看看:

  • *使用对称密钥/证书加密:*一个对称密钥*是一个二进制或十六进制字符序列,它与加密算法一起用来加密数据。服务器和客户端必须使用相同的密钥进行加密和解密。为了进一步增强安全性,可能需要包含公钥和私钥对的证书*。客户端应用程序必须有这个对可用于解密。使用证书和对称密钥进行加密的真正优势是它提供的粒度。例如,你可以只加密单个表中的单个列(图 1-4)——不需要加密整个表或数据库(如 TDE)。加密和解密是 CPU 密集型操作,会占用宝贵的处理资源。这也使得加密数据的检索速度比未加密数据慢。最后,加密数据需要更多的存储空间。因此,如果数据库中只有一小部分包含敏感数据,那么使用该选项是有意义的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1-4 。使用对称密钥和证书创建列级加密

  • TDE: TDE 是 SQL Server 提供的使用对称密钥和证书对数据库进行完全加密的机制。一旦启用了数据库加密,数据库中的所有数据在存储到磁盘上时都会被加密。这种加密对请求数据的任何客户端都是透明的,因为数据在从磁盘传输到缓冲区时会自动解密。图 1-5 详细描述了为数据库实现 TDE 的步骤。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1-5 。为 SQL Server 数据库实现 TDE 的过程

  • **使用加密连接:**该选项包括加密客户端到 SQL 服务器的连接,并确保传输中的数据是加密的。在服务器端,您必须将服务器配置为接受加密连接,创建证书,并将其导出到需要使用加密的客户端。然后,客户端的用户必须在客户端上安装导出的证书,配置客户端以请求加密连接,并打开到服务器的加密连接。

图 1-6 描绘了 SQL Server 安全的各个级别。如您所见,可以在访问的每个阶段过滤数据(根据需要),为用户授权提供粒度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 1-6 。包含详细信息的 SQL Server 安全层

Hadoop 也是一个分布式系统,可以从您在这里学到的许多原则中受益。在接下来的两章中,我将介绍 Hadoop,并概述 Hadoop 的安全架构(或者说缺乏安全架构)。

摘要

本章介绍了一般的安全概念,以帮助您更好地理解和欣赏将用于保护 Hadoop 的各种技术。但是,请记住,理解安全的心理因素和技术一样重要。如果你轻易地将你的密码提供给黑客,没有任何安全协议可以帮助你!

保护一个程序需要了解潜在的缺陷,这样你才能应对它们。通过在 SDLC 的每个阶段进行质量控制,并在实现阶段进行大量测试,可以减少或消除非恶意缺陷。专门的反病毒软件和程序纪律是解决形式化缺陷的唯一方法。

分布式系统由于其体系结构而需要多级安全性,这种体系结构将数据分布在多个主机上,并通过在多个位置执行的多个进程来修改数据。因此,重要的是设计能够在多个级别上工作的安全性,并根据主机的角色来保护系统中的各种主机(例如,中央主机或主控主机所需的安全性与其他主机不同)。大多数情况下,这些级别是认证、授权和加密。

最后,计算世界正在快速变化,新的威胁每天都在演变。设计一个安全的系统很重要,但保持系统的更新也同样重要。昨天还是最好的安全系统现在已经不够好了。今天必须是最好的,明天也可能是最好的!


1 请参考 Jonathan Pincus 和 Brandon Baker 撰写的 IEEE 论文“超越堆栈粉碎:利用缓冲区溢出的最新进展”,了解关于这类攻击的更多详细信息。该文章的 PDF 可在

http://classes.soe.ucsc.edu/cmps223/Spring09/Pincus%2004.pdf

获得。**

二、Hadoop 简介

我参加了一个数据仓库会议,与一家领先银行的高管谈论 Hadoop。当我告诉他这项技术时,他插话道:“但是它对我们有什么用处吗?我们没有任何互联网使用情况可以分析!”他只是表达了一个普遍的误解。Hadoop 不仅仅是一种用于分析网络使用或日志文件的技术;它在 Pb(每个 1,000)的世界中有真正的用途。这是一项超级智能的技术,可以帮助您高效快速地管理大量数据,而无需在硬件上花费大量资金。

Hadoop 可能始于实验室,一些真正聪明的人使用它来分析数据以实现行为目的,但它今天在企业界越来越受到支持。为了在这种新环境中生存,it 需要进行一些改变(例如增加安全性),但随着这些改变的出现,越来越多的公司开始意识到它为管理和处理大量数据带来的好处。

例如,福特汽车公司使用大数据技术处理他们的混合动力汽车产生的大量数据(每小时约 25GB),分析、总结并通过移动应用程序呈现给司机,该应用程序提供有关汽车性能、最近的充电站等信息。使用大数据解决方案,福特还通过消费者对其汽车的反馈和评论来分析社交媒体上的可用数据。使用传统的数据管理和分析工具来分析如此大量的不同数据是不可能的。

社交网站 LinkedIn 使用 Hadoop 以及定制开发的分布式数据库 Voldemort 和 Espresso 来增强其海量数据,使其能够快速提供热门功能,如“你可能认识的人”列表或 LinkedIn 社交图,只需点击一下。这对于传统的数据库或存储来说是不可能的。

Hadoop 使用低成本商用硬件和内置冗余,这是它吸引大多数将其用于存储或归档的公司的主要因素。此外,分布式处理等功能可以将您的处理能力乘以节点数,轻松处理数 Pb 的数据;无需停机即可扩展容量;高度的容错能力使得 Hadoop 对越来越多的企业用户具有吸引力。

在接下来的几节中,您将了解 Hadoop 架构、Hadoop 堆栈,以及 Hadoop 架构固有的安全问题。请注意,在本章中,我将只简要讨论这些安全问题;第四章包含了关于这些问题的更详细的讨论,以及可能的解决方案。

Hadoop 架构

网站将 Hadoop 定义为“一个框架,允许使用简单的编程模型在计算机集群上分布式处理大型数据集。”很简单,这就是哲学:提供一个易于使用、易于扩展的框架,并为生产使用提供容错和高可用性。

这个想法是利用现有的低成本硬件来建立一个强大的系统,可以非常高效和快速地处理数 Pb 的数据。Hadoop 通过将数据本地存储在其 DataNodes 上并在本地进行处理来实现这一点。所有这些都由 Hadoop 系统的大脑 NameNode 高效管理。所有客户端应用程序都通过 NameNode 读取/写入数据,正如您在图 2-1 的简单 Hadoop 集群中看到的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-1 。使用 NameNode(大脑)和 DataNodes 进行数据存储的简单 Hadoop 集群

Hadoop 有两个主要组件:Hadoop 分布式文件系统(HDFS)和一个使用 MapReduce 范式并行处理大量数据的框架。让我先把你介绍给 HDFS。

HDFS

HDFS 是一个分布式文件系统层,位于操作系统的原生文件系统之上。例如,对于 Ubuntu 操作系统,HDFS 可以安装在 ext3、ext4 或 XFS 文件系统之上。它使用廉价、不可靠的硬件为大量数据提供冗余存储。在加载时,数据分布在所有节点上。这有助于高效的 MapReduce 处理。与大量小文件相比,HDFS 处理少量大文件(数千兆字节)的性能更好,这是其设计方式决定的。

文件是“写一次,读多次”新版本的文件现在提供了追加支持,但 HDFS 是针对大型流读取的,而不是随机访问。高持续吞吐量比低延迟更受青睐。

HDFS 中的文件存储为,并为冗余或可靠性进行复制。默认情况下,数据块会跨 DataNodes 复制三次;所以每个文件都有三份拷贝。此外,块大小比其他文件系统大得多。例如,NTFS(用于 Windows)的最大块大小为 4KB,Linux ext3 的默认值为 4KB。与 HDFS 使用的默认块大小 64MB 相比!

NameNode

NameNode(或“大脑”)存储元数据并协调对 HDFS 的访问。元数据存储在 NameNode 的 RAM 中,以便快速检索并减少响应时间(对于 NameNode ),同时提供数据块的地址。这种配置提供了简单的集中式管理,同时也为 HDFS 提供了单点故障(SPOF)。在以前的版本中,辅助 NameNode 提供从 NameNode 故障中恢复的功能;但当前版本提供了在主动/被动配置中群集热备用(备用节点接管 NameNode 的所有功能,无需任何用户干预)节点的能力,以消除 NameNode 的 SPOF,并提供 NameNode 冗余。

由于元数据存储在 NameNode 的 RAM 中,并且文件的每个条目(及其块位置)都会占用一些空间,因此大量的小文件会产生大量的条目,并且会比大文件的少量条目占用更多的 RAM。此外,小于块大小(最小块大小为 64 MB)的文件仍将被映射到单个块,保留它们不需要的空间;这就是为什么大文件比小文件更适合使用 HDFS 的原因。

图 2-2 展示了 HDFS 集群各组成部分之间的关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-2 。HDFS 集群及其组件

HDFS 文件存储和数据块复制

HDFS 文件存储和复制系统的重要之处在于其内置的块放置智能,这提供了更好的节点故障恢复能力。当 NameNode 处理文件存储请求(来自客户端)时,它会在客户端本地存储块的第一个副本—如果它是群集的一部分。如果没有,NameNode 会将它存储在一个不太满或不太忙的 DataNode 上。它将数据块的第二个副本存储在位于同一机架上的不同 DataNode 上(是的,HDFS 在决定数据块放置时会考虑 DataNode 的机架使用情况),并将第三个副本存储在位于不同机架上的 DataNode 上,只是为了降低由于机架故障而丢失全部数据的风险。图 2-2 展示了两个文件的两个副本(每个块的)是如何分布在可用的数据节点上的。

DataNode 向 NameNode 发送心跳,如果 DataNode 在特定时间内没有发送心跳,则认为它“丢失”NameNode 找到其他 DataNode(该 DataNode 上有数据块的副本),并指示它们将丢失的数据块复制到另一个 DataNode。这样,所有数据块的副本总数将始终与配置的复制因子相匹配(该因子决定将维护文件的多少个副本)。

添加或删除 DataNodes

在 HDFS 集群中添加或删除 DataNodes 非常容易。您只需要将新的 DataNode 的主机名添加到一个配置文件(一个名为

slaves

的文本文件)中,并运行一个管理实用程序来告诉 NameNode 这个添加。之后,在新的 DataNode 上启动 DataNode 进程,并且您的 HDFS 集群有了一个额外的 DataNode。

删除 DataNode 同样简单,只需要一个相反的过程——从

slaves

中删除主机名条目,然后运行管理实用程序让 NameNode 知道这一删除。此后,可以关闭该节点上的 DataNode 进程,并将其从 HDFS 集群中删除。NameNode 悄悄地将块(从退役的 DataNode)复制到其他 DataNode,生活继续进行。

集群重新平衡

添加或删除 DataNodes 很容易,但这可能会导致您的 HDFS 集群不平衡。在你的 HDFS 集群中,还有其他可能造成不平衡的活动。Hadoop 提供了一个实用程序(Hadoop Balancer ),可以再次平衡您的集群。平衡器将数据块从过度利用的数据节点移动到未充分利用的数据节点,同时仍然遵循 Hadoop 的存储和复制策略,即不将数据节点上的所有副本放在一个机架上。

数据块移动将持续进行,直到所有数据节点的利用率(已用空间与总容量的比率)都在彼此的阈值百分比范围内。例如,5%的阈值意味着所有 DataNodes 的利用率都在 5%以内。平衡器在后台以低带宽运行,不会加重集群负担。

磁盘存储器

HDFS 为 NameNode、辅助 NameNode 和 DataNodes 使用本地存储,因此使用正确的存储类型非常重要。作为集群的大脑,NameNode 需要冗余和容错存储。强烈建议使用 RAID 10(在至少两个磁盘上对数据进行条带化和镜像)。辅助 NameNode 需要 RAID 10 存储。就 DataNodes 而言,它们可以使用本地 JBOD(只是一堆磁盘)存储。请记住,这些节点上的数据已经复制了三次(或者无论复制因子是什么),因此没有使用 RAID 驱动器的实际需要。

辅助 NameNode

现在让我们考虑一下辅助 NameNode 如何维护 NameNode 元数据的备用副本。NameNode 使用一个名为

fsimage

的图像文件来存储 HDFS 的当前状态(存储在文件系统中的所有文件及其对应块的位置的地图),并使用一个名为

edits

的文件来存储对 HDFS 的修改。随着时间的推移,

edits

文件会变得非常大;因此,

fsimage

不会有正确反映 HDFS 状态的最新图像。在这种情况下,如果 NameNode 崩溃,HDFS 的当前状态将会丢失,数据将不可用。

为了避免这种情况,辅助 NameNode 执行检查点(默认情况下每小时一次),在本地合并 NameNode 的

fsimage

edits

文件,并将结果复制回 NameNode。因此,在最坏的情况下,只有对 HDFS 的编辑或修改会丢失——因为辅助 NameNode 在本地存储了最新的

fsimage

副本。图 2-3 提供了对这一过程的更多了解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-3 。由辅助 NameNode 执行的检查点

所有这些对您的数据意味着什么?考虑一下 HDFS 是如何处理请求的。图 2-4 显示了 NameNode 如何处理数据请求,以及如何从相应的 DataNodes 中检索数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-4 。Hadoop 数据访问请求剖析

NameNode 高可用性

正如您在名称节点一节中所记得的,名称节点是一个 SPOF。但是,如果将 Hadoop 集群用作生产系统,就需要有一种方法来消除这种依赖性,并确保集群即使在 NameNode 失败的情况下也能正常工作。应对 NameNode 故障的方法之一是使用 NameNode 高可用性(或 HA ),其中一个集群部署有一对主动/被动的 NameNode。

edits

预写日志需要对两个 NameNodes(主动/被动)都可用,因此位于共享的 NFS 目录中。活动 NameNode 写入

edits

日志,备用 NameNode 重放相同的事务,以确保它是最新的(准备好在出现故障时接管)。DataNodes 向两个节点发送数据块报告。

您可以为手动或自动故障转移配置 HA 命名节点对(主动和被动节点互换角色)。对于手动故障转移,需要执行一个命令,让备用 NameNode 接管主 NameNode 或活动 NameNode。对于自动故障转移,每个 NameNode 需要运行一个称为故障转移控制器的额外进程,用于监控 NameNode 进程并根据需要协调状态转换。ZooKeeper 应用程序通常用于管理故障转移。

在故障转移的情况下,无法确定活动 NameNode 是否不可用,或者是否无法从备用 NameNode 访问它。如果两个 NameNode 进程并行运行,它们都可以写入共享状态并破坏文件系统元数据。这构成了裂脑场景,为了避免这种情况,您需要确保失败的 NameNode 被停止或“隔离”越来越严格的技术被用来实现击剑;从通过 RPC(远程过程调用)向 STONITH (或“击中另一个节点的头部”)发出停止请求开始,通过发出远程重启或(以编程方式)短时间切断机器电源来实现。

使用 HA 时,由于备用 NameNode 接管了辅助 NameNode 的角色,因此不需要单独的辅助 NameNode 进程。

hdfs 架构的互联网安全问题

回顾 HDFS 架构后,您会发现这不是我们都习惯的处理数据的传统客户端/服务器模型。没有服务器来处理数据、验证用户或管理锁定。在最初的 Hadoop 设计中,没有安全网关或认证机制。尽管 Hadoop 现在内置了强大的认证(您将在后面看到),但与现有企业系统和基于角色的授权集成的复杂性仍然带来了挑战。

任何能够访问运行 NameNode 进程的服务器并对 Hadoop 二进制文件拥有执行权限的用户都有可能从 NameNode 请求数据并请求删除这些数据!访问权限仅受 Hadoop 目录和文件权限的限制;但是很容易模仿另一个用户(在这种情况下是 Hadoop 超级用户)并访问一切。此外,Hadoop 不支持基于角色的访问或对象级访问,也不支持足够粒度的属性级访问(针对特定对象)。例如,它不提供能够运行特定 Hadoop 守护进程(或服务)的特殊角色。管理员角色中有一个全能的 Hadoop 超级用户,但是其他人都是凡人。除非为特定所有者或组指定了文件访问权限,否则用户只需连接到 HDFS 并访问所有文件。

因此,Hadoop 架构提供的灵活性也因缺乏中央认证机制而产生了漏洞。由于数据分布在大量的 datanode 上,再加上分布式存储和处理的优势,datanode 也是潜在的攻击入口,需要很好地保护。

Hadoop 客户端使用 RPC 协议在 NameNode 执行元数据操作,如创建文件打开文件,并使用称为数据传输协议的流套接字协议直接从 DataNodes 读取/写入文件数据。通过 Hadoop 配置文件可以轻松加密通过 RPC 协议完成的通信,但加密 DataNodes 和客户端之间的数据流量需要使用 Kerberos 或 SASL(简单认证和安全层)框架。

web 控制台和 Hadoop 守护进程(NameNode、辅助 NameNode、DataNode 等)之间的 HTTP 通信。)是不加密和不安全的(默认情况下,它允许在没有任何形式的认证的情况下访问),如图 2-5 所示。因此,访问所有集群元数据非常容易。总而言之,HDFS 因其建筑而面临以下威胁:

  • 未经授权的客户端可以通过 RPC 或 HTTP 协议访问 HDFS 文件或群集元数据(因为默认情况下通信是不加密和不安全的)。
  • 未经授权的客户端可以通过管道流数据传输协议(同样,未加密的通信)在 DataNode 读取/写入文件的数据块。
  • 任务或节点可能伪装成 Hadoop 服务组件(如 DataNode ),并修改元数据或执行破坏性活动。
  • 具有网络访问权限的恶意用户可以截获未加密的节点间通信。
  • 如果处理不当,大型 Hadoop 集群中故障磁盘上的数据可能会泄露私人信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-5 。Hadoop 通信协议和漏洞

当 Hadoop 守护进程(或服务)相互通信时,它们不会验证另一个服务是否真的是它所声称的那样。因此,很容易启动一个流氓 TaskTracker 来访问数据块。有一些方法可以让 Hadoop 服务执行相互认证;但是 Hadoop 在默认情况下不会实现它们,它们需要配置更改以及一些额外的组件来安装。图 2-5 总结了这些威胁。

我们将在第四章和第五章(涵盖认证和授权)以及第八章(重点是加密)中更详细地讨论安全问题(以及相关的解决方案)。现在,将注意力转向 Hadoop 的另一个主要组件:使用 MapReduce 范式并行处理大量数据的框架。

使用 MapReduce 的 Hadoop 作业框架

在前面的章节中,我们回顾了 Hadoop 的一个方面:HDFS,它负责跨多个 DataNodes 分发(和存储)数据。另一方面是数据的分布式处理;这是由 Hadoop 的作业框架处理的,它使用 MapReduce。

MapReduce 是一种跨多个节点分配任务的方法。每个节点处理存储在该节点上的数据(如果可能)。它由两个阶段组成:映射和还原。Map 任务处理一个分割或部分输入数据(一个键-值对),转换它,并输出转换后的中间数据。然后在一个洗牌(排序)过程中节点之间有数据交换,同一个 key 的中间数据到同一个 Reducer

Reducer 从不同的映射器接收输出时,它使用键(键-值对)对输入的数据进行排序,并将同一键的所有值组合在一起。然后 reduce 方法被 reduce 调用。它通过迭代与给定键相关联的值来生成一个键-值对列表(可能为空),并将输出写入输出文件。

MapReduce 框架利用两个 Hadoop 守护进程(JobTracker 和 TaskTracker)来调度和处理 MapReduce 作业。 JobTracker 在主节点(通常是运行 NameNode 的同一个节点)上运行,并管理为 Hadoop 集群提交的所有作业。JobTracker 使用从属节点(DataNodes)上的多个task tracker根据需要处理部分作业。

一个任务尝试是在一个从(TaskTracker)节点上运行的一个任务的实例。任务尝试可能会失败,在这种情况下,它们将被重新启动。因此,至少会有与需要执行的任务一样多的任务尝试。

随后,MapReduce 程序导致以下步骤:

  1. 客户端程序向 Hadoop 提交一个作业(数据请求)。
  2. 该作业由一个映射器、一个缩减器和一个输入列表组成。
  3. 作业被发送到主节点上的 JobTracker 进程。
  4. 每个从节点运行一个名为 TaskTracker 的进程。
  5. JobTracker 指示 TaskTrackers 运行和监视任务(输入数据的映射或简化任务)。

图 2-6 说明了 Hadoop 的 MapReduce 框架以及它如何处理一个任务。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-6 。MapReduce 框架和作业处理

任务进程向 TaskTracker 发送心跳。TaskTrackers 向 JobTracker 发送心跳。任何未能在 10 分钟内报告的任务都将被视为失败,并被 TaskTracker 终止。此外,任何抛出异常的任务都被认为是失败的。

任务跟踪者将失败的任务报告给任务跟踪者。JobTracker 重新计划任何失败的任务,并试图避免在先前失败的同一 TaskTracker 上重新计划任务。如果一项任务失败超过四次,则整个作业都会失败。任何未能在 10 分钟内报告的 TaskTracker 被认为已经崩溃,所有分配的任务在另一个 TaskTracker 节点上重新开始。

任何报告大量失败任务的 TaskTracker 都被列入黑名单(以防止节点阻塞整个作业)。还有一个针对多个任务失败的 TaskTrackers 的全局黑名单。JobTracker 管理每个作业的状态,失败任务的部分结果将被忽略。

图 2-7 显示了 MapReduce 范式如何为输入键值对工作,并导致输出减少。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-7 。作业的 MapReduce 处理

对 MapReduce 的详细介绍超出了本书的范围;感兴趣的读者可以参考 Jason Venner 的Pro Hadoop(a press,2009)。Jason 在的第二章中介绍了 MapReduce,并在的第五章中详细讨论了 MapReduce 程序的结构。MapReduce 的每个组件都被详细讨论,提供了一个深入的理解。

Apache Hadoop 纱线

Hadoop 早期版本使用的 MapReduce 算法在许多情况下不足以满足需要定制资源处理的场景。有了 YARN,Hadoop 现在有了一个通用的分布式数据处理框架(带有内置的调度程序),可以用来定义自己的资源处理。Hadoop MapReduce 现在只是可以与 YARN 一起使用的分布式数据处理应用程序之一。

YARN 将 JobTracker 的两个主要功能(资源管理和作业调度/监控)分配给单独的守护进程:一个全局资源管理器和一个基于应用程序的 ApplicationMaster。ResourceManager 和 NodeManager(运行在每个“从属”节点上)与 ApplicationMaster 一起构成了一个通用的分布式数据处理系统。

ResourceManager 是为集群中所有分布式数据处理应用程序分配资源的总权威。ResourceManager 使用一个可插拔的调度器(由您选择,例如,公平或先进先出[FIFO]调度器),负责根据应用程序的需求为其分配资源。此计划程序不执行监控、跟踪状态或重新启动失败的任务。

每个应用程序的 ApplicationMaster 与 ResourceManager 协商资源,与 NodeManager 一起执行组件任务,跟踪它们的状态,并监视它们的进度。这项功能先前是由 TaskTracker 执行的(当然还有调度)。

NodeManager 负责启动应用程序的容器,监视它们的资源使用情况(CPU、内存、磁盘、网络),并将其报告给 ResourceManager。

那么,MapReduce 和 YARN 有什么区别呢?如前所述,YARN 将 JobTracker 的功能分为 ResourceManager(调度)和 Application Master(资源管理)。有趣的是,这也将所有特定于应用程序框架的代码移动到 ApplicationMaster,使系统通用化,以便支持多种分布式处理框架,如 MapReduce、MPI(消息传递接口,一种用于并行计算机的消息传递系统,用于开发许多可扩展的大规模并行应用程序)和图形处理。

Hadoop 作业框架的固有安全问题

MapReduce 框架的安全问题围绕着 Hadoop 中缺乏认证、Hadoop 守护程序之间的通信不安全以及 Hadoop 守护程序不相互进行认证这一事实。主要的安全问题如下:

  • 未经授权的用户可能会向队列提交作业,或者删除或更改作业的优先级(因为 Hadoop 不进行认证或授权,并且很容易冒充用户)。
  • 未经授权的客户端可能会通过其 TaskTracker 的 HTTP shuffle 协议(未加密且不安全)访问地图作业的中间数据。
  • 正在执行的任务可以使用主机操作系统接口来访问其他任务和本地数据,包括中间映射输出或在同一物理节点上运行的 DataNode 的本地存储(静态数据是未加密的)。
  • 任务或节点可能伪装成 Hadoop 服务组件,如 DataNode、NameNode、JobTracker、TaskTracker 等。(无主机进程认证)。
  • 一个用户可能作为另一个用户提交一个工作流(使用像 Oozie 这样的工作流包)(很容易模拟一个用户)。

正如你所记得的,图 2-6 展示了 MapReduce 框架如何处理一个任务。比较图 2-6 和图 2-8 会让你更好地了解 MapReduce 框架的安全问题。图 2-8 详细描述了相同上下文中的安全问题:作业执行。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-8 。MapReduce 框架漏洞

Hadoop 的运营安全困境

到目前为止,我们讨论的安全问题源于 Hadoop 的架构,而不是我们每天都要处理的运营问题。一些问题源于 Hadoop 相对较新,起源于隔离的安全环境中的隔离实验室。曾经有一段时间,通过严格限制对 Hadoop 集群的网络访问,Hadoop 是“安全的”。任何访问请求都必须附有安全部门和请求者自己的管理层的几份弃权书!

此外,一些现有技术还没有时间构建接口或提供网关来与 Hadoop 集成。例如,当你读到这篇文章的时候,一些现在缺失的特性可能已经被添加了。像过去的 Unix 一样,Hadoop 仍然是一项正在进行的工作,每天都有新功能和新技术加入。考虑到这一点,请考虑 Hadoop 目前面临的一些运营安全挑战。

无法使用现有的用户凭据和策略

假设您的组织使用单点登录或 active directory 域帐户连接到所使用的各种应用程序。如何在 Hadoop 中使用它们?嗯,Hadoop 确实提供了 LDAP(轻量级目录访问协议)集成,但配置它并不容易,因为这个接口仍处于萌芽阶段,文档也非常粗略(在某些情况下甚至没有文档)。这种情况由于 Hadoop 在各种 Linux 版本上的使用而变得更加复杂,并且问题因所使用的操作系统及其版本而异。因此,向 active directory 用户分配选择性 Hadoop 资源并不总是可行的。

此外,您如何实现现有的访问控制策略,例如应用程序用户的读权限、开发人员的读/写权限等等?答案是不能。最简单的方法是为 Hadoop 访问创建单独的凭据,并遵循组织策略手动重新建立访问控制。Hadoop 遵循自己的安全模型,它(在外观上)类似于 Linux,让很多人感到困惑。Hadoop 和 Hadoop 生态系统结合了许多具有不同配置端点和各种授权方法(基于 POSIX 文件、类似 SQL 数据库)的组件,这可能会给开发和维护安全授权策略带来巨大挑战。社区有解决这些问题的项目(例如 Apache Sentry 和 Argus),但在撰写本文时还没有全面的解决方案。

难以与企业安全集成

大多数组织使用企业安全解决方案来实现各种目标。有时是为了降低网络攻击的风险,为了安全合规,或者仅仅是为了建立客户信任。然而,Hadoop 无法与这些安全解决方案集成。也许可以写一个自定义插件来适应 Hadoop 但是让 Hadoop 遵守所有的安全政策可能是不可能的。

传输中的未加密数据

Hadoop 是一个分布式系统,因此由多个节点(如 NameNode 和多个 DataNodes)组成,它们之间进行数据通信。这意味着数据通过网络传输,但没有加密。这可能是敏感的财务数据,如帐户信息或个人数据(如社会安全号码),并且容易受到攻击。

Hadoop 中的节点间通信使用 RPC、TCP/IP 和 HTTP 等协议。目前,只有 RPC 通信可以轻松加密(即 NameNode、JobTracker、datanode 和 Hadoop 客户端之间的通信),从而使客户端和 datanode(TCP/IP)之间的文件数据的实际读/写以及 HTTP 通信(web 控制台、NameNode/辅助 NameNode 和 MapReduce shuffle 数据之间的通信)容易受到攻击。

可以加密 TCP/IP 或 HTTP 通信;但这需要使用 Kerberos 或 SASL(简单认证和安全层)框架。还有,Hadoop 的内置加密对性能有非常负面的影响,没有被广泛使用。

静态无数据加密

静止时,数据存储在磁盘上。Hadoop 不加密存储在磁盘上的数据,这可能会将敏感数据暴露给恶意攻击。目前,没有为此目的提供编解码器或框架。由于 Hadoop 架构的性质,这尤其是一个大问题,它将数据分布在大量节点上,在所有这些不安全的入口点暴露数据块。

使用 Hadoop 实现静态加密有多种选择;但是它们是由不同的供应商提供的,并且依赖于它们的发行版来实现加密。最值得注意的是英特尔 Hadoop 发行版,它为存储在磁盘上的数据提供加密,并使用 Apache 和自定义编解码器来加密数据。其中一些功能被提议通过 Project Rhino(一个 Apache 开源项目)提供。

您必须了解,由于 Hadoop 通常处理大量数据,加密/解密需要时间,因此所用框架足够快地执行加密/解密非常重要,这样才不会影响性能。英特尔发行版声称能够以极高的速度执行这些操作——前提是英特尔 CPU 与英特尔磁盘驱动器和所有其他相关硬件一起使用。

Hadoop 不跟踪数据来源

存在多步骤 MapReduce 作业在中间步骤失败的情况,并且由于执行通常是面向批处理的,因此很难调试失败,因为输出数据集是所有可用的。

数据起源 是一个捕捉数据如何通过工作流处理的过程,并通过启用回溯来帮助调试——查找导致任何给定步骤的输出的输入数据。如果输出不寻常(或者不是预期的),可以使用反向跟踪来确定被处理的输入。

Hadoop 不提供任何数据起源(或回溯)的工具;如果需要数据来源,需要使用 RAMP 等第三方工具。这使得排除作业故障变得非常困难和耗时。

我们对 Hadoop 架构和相关安全问题的讨论到此结束。接下来我们将讨论 Hadoop 堆栈。

Hadoop 堆栈

Hadoop 核心模块和主要组件被称为 Hadoop 堆栈。Hadoop核心模块共同为 Hadoop 集群提供基本的工作功能。Hadoop 公共模块提供共享库,HDFS 提供分布式存储和容错文件系统的功能。MapReduce 或 YARN 提供了分布式数据处理功能。因此,没有所有的华而不实,这是一个功能性的 Hadoop 集群。您可以将一个节点配置为 NameNode,并为一个基本的、正常工作的 Hadoop 集群添加几个 DataNodes。

下面是对每个核心模块的简要介绍:

  • Hadoop Common :这些是支持其他 Hadoop 模块功能的公共库或实用程序。由于其他模块大量使用这些库,这是 Hadoop 的主干,对其工作是绝对必要的。
  • Hadoop 分布式文件系统(HDFS) : HDFS 是 Hadoop 集群的核心。它是一个分布式的文件系统,具有容错能力,易于扩展,并在数据节点上使用本地处理和本地数据存储来提供高吞吐量。(我已经在“HDFS”一节中非常详细地讨论了 HDFS)。
  • Hadoop YARN: YARN is a framework for job scheduling and cluster resource management. It uses a global resource manager process to effectively manage data processing resources for a Hadoop cluster in conjunction with Node Manager on each data node.资源管理器还有一个可插拔调度器(可以使用任何调度器,如 FIFO 或 Fair 调度器),它可以调度作业并与 DataNodes 上的应用程序主进程一起工作。默认情况下,它使用 MapReduce 作为分布式数据处理算法,但也可以根据需要使用任何其他分布式处理应用程序。
  • Hadoop MapReduce :基于 YARN 的大数据集并行处理系统。MapReduce 是“处理数据”的算法所有数据节点都可以本地、独立和并行地处理映射(输入到所需输出的转换)和归约(输出的排序和合并),以提供超大型数据集所需的高吞吐量。我在前面的“使用 MapReduce 的 Hadoop 作业框架”一节中详细讨论了 MapReduce。

那么,你现在知道 Hadoop 核心模块是什么了,但是它们是如何相互关联以形成具有预期功能的内聚系统的呢?图 2-9 说明了相互连接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 2-9 。Hadoop 核心模块及其相互关系

如您所见,Hadoop 的两个主要方面是分布式存储和分布式数据处理。您还可以清楚地看到这两个方面对 Hadoop 公共库和操作系统的依赖性。Hadoop 就像运行在操作系统环境中的任何其他应用程序一样。但是安全系统会怎么样呢?是从操作系统继承来的吗?这就是问题所在。安全性不是从操作系统继承的,Hadoop 的安全性虽然有所提高,但仍不成熟,难以配置。因此,您必须找到在 Hadoop 集群中对数据进行认证、授权和加密的方法。你将在第四章、第五章、第八章和第九章中学习这些技巧。

最后,请注意在现实世界中,在同一个节点上运行 NameNode(管理 HDFS 处理)和 JobTracker(管理作业处理)是很常见的。因此,图 2-9 仅表示加工的逻辑划分;在物理实现的情况下不一定如此。

Hadoop 的主要组件

正如您在上一节中看到的,Hadoop 核心模块提供了基本的 Hadoop 集群功能,但主要组件并不局限于核心模块。毕竟一个基本的 Hadoop 集群是不能作为生产环境的。任何数据存储和管理系统都需要额外的功能,例如 ETL 和从其他(非 Hadoop)数据源的批量加载功能、调度、快速基于键的检索和查询功能(针对数据)。Hadoop 的主要组件也提供了这些缺失的功能。

例如,Pig 组件提供了一种用于设计 ETL 的数据流语言。Sqoop 提供了一种在 HDFS 和关系数据库之间传输数据的方法。Hive 使用类似 SQL 的语言提供查询功能。Oozie 提供了调度功能,HBase 为海量数据存储和基于键的快速检索添加了列存储。表 2-1 列出了一些流行的组件及其用法。

表 2-1 。流行的 Hadoop 组件

|

成分

|

描述

|

笔记

|
| — | — | — |
| 巴什 | HBase 是一个开源、分布式、版本化、面向列的数据存储。 | 它可用于存储大量结构化和非结构化数据。它提供基于键的数据访问,因此可以非常快速地检索数据。它高度可扩展,并使用 HDFS 进行数据存储。HBase 的真正优势在于它能够存储非结构化的无模式数据,并使用行键快速检索这些数据。 |
| 储备 | Hive 提供了一种类似 SQL 的查询语言(HiveQL ),可用于查询 HDFS 数据。 | Hive 将查询转换为 MapReduce 作业,运行它们,并显示结果。Hive“表格”实际上是 HDFS 内部的文件。Hive 适合用于数据仓库,因为它不支持行级的插入、更新或删除。现在,脸书超过 95%的 Hadoop 工作都是由 Hive 前端驱动的。 |
| 猪 | Pig 是一种数据流语言,可以有效地用作仓库环境的 ETL 系统。 | 就像几乎什么都吃的真正的猪一样,猪编程语言被设计成处理任何类型的数据——因此得名。使用 Pig,您可以加载想要操作的 HDFS 数据,通过一组转换运行数据(在后台,这些数据被转换为 MapReduce 任务),并在屏幕上显示结果或将结果写入文件。 |
| Sqoop | Sqoop 提供与关系数据库(微软 SQL Server、Oracle、MySQL 等)的连接。),数据仓库,以及 NoSQL 数据库(Cassandra,HBase,MongoDB 等。). | 使用 Sqoop“连接器”可以很容易地在 HDFS(或 Hive/HBase 表)和这些数据源之间传输数据 Sqoop 与 Oozie 集成,以调度数据传输任务。Sqoop 的第一个版本是命令行客户端;但是 Sqoop2 有一个 GUI 前端和一个可以与多个 Sqoop 客户端一起使用的服务器。 |
| 驭象者 | Oozie 是一个工作流调度器,这意味着它基于工作流运行作业。在这个上下文中,工作流是安排在控制依赖 DAG(直接非循环图)中的动作的集合。 | 动作之间的控制依赖关系简单地定义了动作的顺序;比如第一个动作完成后,第二个动作才能开始。DAG 指的是一个无环图,它有一个起点和一个终点,并且沿一个方向前进,从不反转。总而言之,Oozie 只是按照预定义的顺序执行动作或作业(考虑到依赖性)。除非 Oozie 收到来自执行当前步骤或作业的远程系统的完成响应,否则不会启动序列中的下一个步骤。Oozie 通常用于调度 Pig 或 Sqoop 工作流,并与它们很好地集成。 |
| 水道 | Flume 是一个分布式系统,用于将大量数据从多个来源(同时根据需要转换或聚合数据)移动到一个集中的目的地或数据存储。 | Flume 有源、装饰器和接收器。是数据源,如日志文件、进程输出、TCP/IP 端口的流量等。,而且 Flume 有许多预定义的源以便于使用。装饰器是对源数据流的操作(如压缩或解压缩数据,从数据流中添加或删除某些字符,对数字数据进行分组和平均等。).接收器是文本文件、控制台显示或 HDFS 文件等目标。Flume 的一个常见用途是将诊断或作业日志文件移动到一个中心位置,并使用关键字(例如,“错误”或“失败”)进行分析。 |
| 象夫 | Mahout 是一个机器学习工具 | 还记得当你访问亚马逊或网飞网站时,它们是如何根据你的浏览历史或之前的购买记录推荐产品的吗?这是 Mahout 或类似的机器学习工具在发挥作用,使用所谓的协作过滤来提出建议,这是 Mahout 使用的机器学习任务之一,它基于用户的点击、评级或过去的购买来生成建议。Mahout 使用其他几种技术来“学习”或理解数据,它提供了开发高度可伸缩的机器学习或数据挖掘库的优秀方法(即,在数据量发生巨大变化的情况下,它们仍然可以使用)。 |

您可能已经注意到没有组件专门用于提供安全性。您将需要使用开源产品,如 Kerberos 和 Sentry,来补充这一功能。你将在第四章和第五章中了解更多。

对主要组件的简要介绍非常重要,因为在讨论安全实现以及监控(第七章)、日志记录(第六章)或加密(第八章和 9)的使用时,我假设整本书都使用“扩展的”Hadoop 集群(核心模块和主要组件)。

摘要

本章介绍了 Hadoop 的架构、核心模块、主要组件和固有的安全问题。

Hadoop 不是一个完美的安全系统,但什么是呢?以及 Hadoop 与之相比如何?为了使 Hadoop 成为一个安全的系统,你需要对它做哪些修改?第一章简要概述了一个模型安全系统(SQL Server),我将在第四章到第八章中讨论如何使用各种技术保护 Hadoop。

在后面的章节中,您还将了解 Hadoop 集群如何使用这里介绍的 Hadoop 堆栈(Hadoop 核心模块和主要组件)。了解 Hadoop 堆栈的工作方式也将使您更容易理解我提出的补充安全性的解决方案。下一章概述了我将在整本书中讨论的解决方案。第三章还将帮助你决定你想要关注的具体解决方案,并指引你找到所需细节的章节。

三、Hadoop 安全性简介

我们生活在一个非常不安全的世界。从你家前门的钥匙到所有重要的虚拟钥匙,你的密码,所有的东西都需要被保护好。在处理、转换和存储海量数据的大数据世界中,保护您的数据更加重要。

几年前,伦敦警方逮捕了一群年轻人,他们涉嫌欺诈和盗窃价值 3000 万美元的数字资产。他们 20 岁的头目使用宙斯木马,从他的笔记本电脑上窃取银行信息的软件来实现犯罪。由于即使在进行简单的业务交易时,也会涉及大量的信息和无数的系统,因此像这样的事件很常见。在过去,可能只有成千上万的人有可能访问你的数据来对你犯罪;现在,随着互联网的出现,可能有数十亿人!同样,在大数据出现之前,只有直接访问特定系统上的特定数据才是危险的;现在,大数据成倍增加了此类信息的存储位置,因此提供了更多方式来泄露您的隐私,甚至更糟。在新技术驱动、互联网驱动的世界中,一切都被扩大和缩小了——包括犯罪和潜在的犯罪。

想象一下,如果您的公司花费数百万美元安装 Hadoop 集群,使用大数据解决方案收集和分析客户对某个产品类别的消费习惯。由于该解决方案不安全,您的竞争对手获得了该数据,您的该产品类别的销售额下降了 20%。系统是如何允许未经授权访问数据的?没有任何认证机制吗?为什么没有警报?这个场景应该让您思考安全性的重要性,尤其是涉及敏感数据的时候。

尽管 Hadoop 由于其分布式架构而存在固有的安全性问题(正如您在第二章中看到的那样),但所描述的情况极不可能发生在安全管理的 Hadoop 安装上。Hadoop 安装明确定义了用户角色和敏感数据的多级认证(和加密),不会让任何未经授权的访问通过。

这一章是本书其余部分的路线图。它简要概述了确保 Hadoop 安装安全所需的每项技术;后面的章节将会更详细地介绍这些主题。目的是提供安全选项的快速概述,并帮助您根据需要快速找到相关技术。我从认证(使用 Kerberos)开始,接着讨论授权(使用 Hadoop ACLs 和 Apache Sentry),然后讨论安全管理(审计日志和监控)。最后,本章研究了 Hadoop 的加密和可用选项。我尽可能使用开源软件,因此您可以轻松构建自己的 Hadoop 集群来尝试本书中描述的一些技术。

然而,作为这一切的基础,您需要了解 Hadoop 的开发方式,并对 Hadoop 架构有所了解。有了这些背景信息,您将更好地理解本章后面讨论的认证和授权技术。

从 Hadoop 安全性开始

当谈到 Hadoop 安全性时,您必须考虑 Hadoop 是如何被概念化的。当 Doug Cutting 和 Mike Cafarella 开始开发 Hadoop 时,安全性并不是他们的首要任务。我确信这甚至不是最初设计的一部分。Hadoop 旨在处理公共领域的大量 web 数据,因此安全性不是开发的重点。这就是为什么它缺乏一个安全模型,只为 HDFS 提供基本的认证——这不是很有用,因为假冒另一个用户非常容易。

另一个问题是 Hadoop 不是作为一个具有预定义模块的内聚系统来设计和开发的,而是作为一个模块的拼贴来开发的,这些模块要么对应于各种开源项目,要么对应于由各种供应商开发的一组(专有)扩展,以补充 Hadoop 生态系统中缺乏的功能。

因此,Hadoop 为其集群的运行假设了一个可信环境的隔离(或茧),而没有任何安全违规——这在大多数情况下是缺乏的。目前,Hadoop 正从实验或新兴技术阶段过渡到企业级和公司使用。这些新用户需要一种方法来保护敏感的业务数据。

目前,社区支持的保护 Hadoop 集群的标准方法是使用 Kerberos 安全性。Hadoop 及其主要组件现在完全支持 Kerberos 认证。不过,这只是增加了一层认证。仅仅添加了 Kerberos,仍然没有一致的内置方法来定义用户角色以更好地控制组件,没有方法来保护对 Hadoop 进程(或守护程序)的访问或加密传输中的数据(甚至静态数据)。一个安全的系统需要解决所有这些问题,还需要提供更多的特性和方法来定制满足特定需求的安全性。在整本书中,您将学习如何在 Hadoop 中使用这些技术。现在,让我们先简单看一下解决 Hadoop 认证问题的流行解决方案。

HDFS 认证授权介绍

安全性的第一个也是最重要的考虑是认证。用户在被允许访问 Hadoop 集群之前需要进行认证。由于 Hadoop 不做任何安全认证,Kerberos 通常与 Hadoop 一起使用来提供认证。

当为了安全而实现 Kerberos 时,一个客户端(试图访问 Hadoop 集群)联系 KDC(托管凭证数据库的中央 Kerberos 服务器)并请求访问。如果提供的凭据有效,KDC 将提供请求的访问权限。我们可以将 Kerberos 认证过程分为三个主要步骤:

  1. TGT 代,其中认证服务器(AS)授予客户端一张票据授予票(TGT) 作为认证令牌。一个客户端可以对多个 TGS 请求使用同一个 TGT(直到 TGT 过期)。
  2. TGS 会话票证生成,客户端使用凭证解密 TGT,然后使用 TGT 从票证授予服务器(TGS) 获取服务票证,该服务器授予服务器对 Hadoop 集群的访问权限。
  3. 服务访问,客户端使用服务票认证并访问 Hadoop 集群。

第四章讨论了 Kerberos 架构的细节,以及如何配置 Kerberos 以用于 Hadoop。此外,您将找到一个分步指南,帮助您设置 Kerberos 为您的 Hadoop 集群提供认证。

授权

实现安全性时,下一步是授权。具体来说,如何在 Hadoop 中实现细粒度的授权和角色?最大的问题是所有信息都存储在文件中,就像在 Linux 主机上一样(毕竟,HDFS 是一个文件系统)。没有表的概念(像关系数据库一样),这使得授权用户对存储的数据进行部分访问变得更加困难。

无论您称之为定义授权细节、设计细粒度授权还是“微调”安全性,这都是一个多步骤的过程。这些步骤是:

  1. 分析你的环境,
  2. 对数据进行分类以便访问,
  3. 确定谁需要访问什么数据,
  4. 确定必要的访问级别,以及
  5. 实现您设计的安全模型。

但是,您必须记住,Hadoop(及其分布式文件系统)将其所有数据存储在文件中,因此您可以设计的安全性粒度是有限的。像 Unix 或 Linux 一样, Hadoop 有一个非常类似于基于 POSIX(可移植操作系统接口)模型的权限模型——很容易将这些权限与 Linux 权限混淆——因此权限粒度仅限于对文件或目录的读或写权限。你可能会说,“有什么问题?我的 Oracle 或 PostgreSQL 数据库在磁盘上以文件形式存储数据,为什么 Hadoop 不一样?”在传统的数据库安全模型中,所有的访问都是通过明确定义的角色来管理的,并通过一个中央服务器进程来引导。相比之下,数据文件存储在 HDFS,没有这样的中央进程和多个服务,如 Hive 或 HBase 可以直接访问 HDFS 文件。

为了让您详细了解使用基于文件/目录的权限可能实现的授权,第五章讨论了相关概念,解释了逻辑过程,并提供了一个详细的实际例子。现在,另一个真实世界的例子,即授权,将帮助您更好地理解这个概念。

设计 Hadoop 授权的真实示例

假设您正在为一家保险公司的索赔管理系统设计安全性,您必须为访问这些数据的所有部门分配角色并设计细粒度的访问。对于这个例子,考虑两个部门的功能需求:呼叫中心和理赔员。

呼叫中心代表接听客户来电,然后在他们满足所有规定条件的情况下提出或记录索赔(例如,由“天灾”造成的损坏不符合索赔条件,因此不能为他们提出索赔)。

索赔调解人查看提交的索赔,并拒绝违反任何监管条件的索赔。然后,该理赔员提交剩余的索赔进行调查,将它们分配给专业理赔员。这些调整人员根据公司规定和他们的具体职能知识评估索赔,以决定最终结果。

自动报告程序挑选最终状态为“已调整”的索赔,并生成适当的信件邮寄给客户,通知他们索赔结果。图 3-1 总结了该系统。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-1 。各部门所需的索赔数据和访问权限

如您所见,呼叫中心代表需要追加索赔数据,而调解人需要修改数据。因为 HDFS 没有更新或删除的规定,所以 adjustors 只需要添加一个新的记录或行(针对索赔及其数据),其中包含更新的数据和新的版本号。一个预定的流程将需要生成一份报告来查找调整后的索赔,并将最终索赔结果邮寄给客户。因此,该流程将需要对索赔数据的读取权限。

在 Hadoop 中,请记住,数据存储在文件中。对于本例,数据存储在名为

Claims

的文件中。每日数据临时存储在名为

Claims_today

的文件中,并在每晚追加到

Claims

文件中。呼叫中心人员使用组

ccenter

,而理赔员使用组

claims

,这意味着

Claims

Claims_today

上的 HDFS 权限看起来像图 3-2 中的所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-2 。HDFS 文件权限

第一个文件

Claims_today

,拥有所有者和组

ccuser

的写权限。因此,属于该组的所有代表都可以写入或附加到该文件。

第二个文件

Claims

,拥有所有者和组

claims

的读写权限。因此,所有的索赔调整人员都可以读取

Claims

数据,并为他们已经完成工作并提供最终结果的索赔添加新行。另外,请注意,您需要在组

claims

中创建一个名为

Reports

的用户,用于访问报告数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传注意示例中讨论的权限是 HDFS 权限,而不是操作系统权限。Hadoop 遵循一个独立的权限模型,该模型看起来与 Linux 相同,但是前面的权限存在于 HDFS 中,而不是 Linux 中。

那么,这些权限满足这个系统的所有功能需求吗?你可以很容易地验证他们这样做。当然,用户

Reports

拥有他不需要的写权限;但是除此之外,所有的功能需求都得到了满足。

我们将在第五章中用一个更详细的例子来讨论这个话题。正如您所观察到的,您分配的权限仅限于完整的数据文件。然而,在现实世界中,您可能需要足够细粒度的权限来访问部分数据文件。你是怎么做到的?下一节将预览如何操作。

Hadoop 的细粒度授权

有时,数据的必要权限与组织的现有组结构不匹配。例如,一家银行可能需要一个备用主管拥有与主管相同的权限集,以防主管休假或生病。因为备份监督者可能只需要监督者权限的子集,所以为他或她设计一个新的组是不实际的。另外,考虑另一种情况,公司帐户被转移到不同的部门,负责迁移的组需要临时访问权限。

HDFS 的新版本支持 ACL(访问控制列表)功能,这在这种情况下将非常有用。使用 ACL,您可以根据需要为特定用户或组指定读/写权限。在银行示例中,如果备份管理员需要对特定“个人帐户”文件的写权限,则可以使用 HDFS ACL 功能来提供必要的写权限,而无需对文件权限进行任何其他更改。对于迁移场景,可以使用 HDFS ACL 为执行迁移的组分配读/写权限。如果您熟悉 POSIX ACLs,HDFS ACL 的工作方式完全相同。第五章在“HDFS 的访问控制列表”一节中再次详细讨论了 Hadoop ACLs。

最后,如何只为数据文件的一部分或数据的某一部分配置权限?也许用户只需要访问非敏感信息。可以进一步配置粒度(用于授权)的唯一方法是使用 NoSQL 数据库(如 Hive)和专用软件(如 Apache Sentry)。您可以将部分文件数据定义为 Hive 中的,然后使用 Sentry 来配置权限。Sentry 与用户和用户组(称为)一起工作,并让您定义规则 (对表的可能操作,如读或写)和角色(一组规则)。一个用户或组可以分配一个或多个角色。第五章提供了一个使用 Hive 和 Sentry 的真实示例,解释了如何为 Hadoop 定义微调授权。第五章的中的也有 Apache Sentry 的架构细节。

安全管理 HDFS

第四章和第五章将带你了解各种认证和授权技术,这些技术有助于保护你的系统,但不是一个完整的解决方案。如果授权用户访问他们未被授权使用的资源,或者未经授权的用户使用不可预见的方法访问 Hadoop 集群上的资源(阅读:黑客攻击),该怎么办?安全管理通过监控或审计所有对集群的访问来帮助您处理这些情况。如果您不能阻止这种类型的访问,您至少需要知道它发生了!Hadoop 为其所有进程提供了广泛的日志记录(也称为守护进程),一些开源工具可以帮助监控集群。(第六章和第七章详细讨论了审计日志记录和监控。)

由于 HDFS 的设计和构建方式,安全管理 HDFS 面临诸多挑战。监控可以提醒您对任何 Hadoop 集群资源的未授权访问,从而有助于提高安全性。然后,您可以根据这些警报的严重性设计针对恶意攻击的对策。虽然 Hadoop 为这种监控提供了指标,但是使用起来很麻烦。当您使用 Nagios 或 Ganglia 等专用软件时,监控会容易得多。此外,Cloudera 和 Hortonworks 的标准 Hadoop 发行版提供了自己的监控模块。最后,您可以捕获和监控 MapReduce 计数器。

审计日志通过记录流向 Hadoop 集群的所有访问来补充安全性。您可以决定日志记录的级别(如仅记录错误,或记录错误和警告等。),而 Log4j 等模块提供的高级日志管理为日志记录过程提供了很多控制和灵活性。第六章提供了 Hadoop 可用的审计日志记录的详细概述(带示例)。作为预览,下一节将简要概述 Hadoop 日志记录。

使用 Hadoop 日志实现安全性

当安全问题发生时,拥有大量可用的活动日志可以帮助您调查问题。因此,在违规发生之前,您应该启用审计日志记录来跟踪对系统的所有访问。你总是可以过滤掉不需要的信息。即使您已经启用了认证和授权,审计集群活动仍然有好处。毕竟,即使是授权用户也可能执行他们无权执行的任务;例如,具有更新权限的用户可以在没有适当批准的情况下更新条目。但是,您必须记住,Hadoop 日志是原始输出。因此,为了使它们对安全管理员有用,需要接收和处理这些日志的工具(注意,一些安装使用 Hadoop 本身来分析审计日志,因此您可以使用 Hadoop 来保护 Hadoop!).

仅仅捕获审计数据是不够的。您还需要捕获 Hadoop 守护进程数据。受联邦监管法律约束的企业,如健康信息携带和责任法案(HIPAA) 和萨班斯-奥克斯利法案(SOX) 就是这种需求的例子。例如,美国法律要求 HIPAA 涵盖的所有企业防止未经授权访问“受保护的健康信息”(患者姓名、地址以及与患者健康和支付记录相关的所有信息)或审计该信息的应用程序。必须遵守 SOX(2002 年美国联邦法律,要求任何美国上市公司的最高管理层单独证明其公司财务信息的准确性)的企业必须审核对应用程序中任何数据对象(如表)的所有访问。他们还必须监控谁提交、管理或查看了可以更改被审核应用程序中任何数据的作业。对于这样的业务案例,您需要捕捉:

  • HDFS 审计日志(记录 Hadoop 内的所有 HDFS 访问活动),
  • MapReduce 审核日志(记录所有提交的作业活动),以及
  • NameNode、DataNode、JobTracker 和 TaskTracker 的 Hadoop 守护进程日志文件。

Log4j API 是 Hadoop 日志记录的核心,无论是审计日志还是 Hadoop 守护进程日志。Log4j 模块提供了广泛的日志记录功能,并包含几个日志记录级别,您可以使用这些级别来按类别限制消息的输出,以及按类别限制(或抑制)消息。例如,如果 Log4j 日志记录级别被定义为 NameNode 日志记录的信息,则对于 NameNode 接收的任何文件访问请求,事件将被写入 NameNode 日志(即,所有信息性消息将被写入 NameNode 日志文件)。

您可以在 Hadoop 守护进程的 URL 上轻松地更改其日志记录级别。例如,

http://jobtracker-host:50030/logLevel

将在此守护程序运行时更改日志记录级别,但当它重新启动时将被重置。如果遇到问题,可以临时更改相应守护进程的日志记录级别,以便于调试。问题解决后,您可以重置日志记录级别。对于守护进程日志级别的永久更改,您需要在 Log4j 配置文件(

log4j.properties

)中更改相应的属性。

Log4j 架构使用一个日志记录器(一个用于日志事件的命名通道,如 NameNode、JobTracker 等。)、一个附加器(日志事件被转发到该附加器,并负责将其写入控制台或文件)和一个布局(日志事件的格式化程序)。日志记录级别(致命、错误、警告、信息、调试和跟踪)以降序显示事件的严重性。最低日志级别用作过滤器;接受日志级别大于或等于指定级别的日志事件,而忽略不太严重的事件。

图 3-3 展示了级别过滤的工作原理。列显示日志记录级别,而行显示与适当的记录器配置相关联的级别。交集标识事件是被允许通过进一步处理(是)还是被丢弃(否)。使用图 3-3 您可以根据配置的日志记录级别,轻松确定日志中将包含的事件类别。例如,如果 NameNode 的日志记录级别设置为 INFO,则属于 INFO、WARN、ERROR 和 FATAL 类别的所有消息都将被写入 NameNode 日志文件。通过查看列信息并观察标记为 YES 的事件级别,您可以很容易地识别出这一点。“跟踪”和“调试”级别被标记为“否”,将被过滤掉。如果 JobTracker 的日志记录级别设置为致命,则只记录致命错误,这从“致命”列中的值可以明显看出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-3 。Log4j 基于事件级别的日志记录级别和包含内容

第六章将全面介绍 Hadoop 日志(以及它在调查安全问题中的用途)。在下一节中,您将了解监控的主要特性。

安全监控

当您想到监控时,您可能会想到需要进行故障排除的可能的性能问题,或者,如果系统资源(如 CPU、内存、磁盘空间)达到阈值,可能会生成警报。但是,您也可以出于安全目的使用监控。例如,如果用户试图访问群集元数据或读取/写入包含敏感数据的文件,或者某个作业试图访问不应该访问的数据,您可以生成警报。更重要的是,您可以监控许多指标来获得有用的安全信息。

监控像 Hadoop 这样的分布式系统更具挑战性,因为监控软件必须监控单个主机,然后在整个系统的上下文中整合数据。例如,DataNode 上的 CPU 消耗没有 NameNode 上的 CPU 消耗重要。那么,系统将如何处理 CPU 消耗警报,或者能够为分布式系统中具有不同角色的主机识别单独的阈值级别?第七章详细回答了这些问题,但现在让我们来看看可以用于安全目的的 Hadoop 指标:

  • NameNode 上的活动统计信息
  • DataNode 的活动统计信息
  • 服务的详细 RPC 信息
  • 针对系统资源突然变化的健康监控

贸易工具

领先的监控工具是 Ganglia (

http://ganglia.sourceforge.net

)和 Nagios (

www.nagios.org

)。这些流行的开源工具互为补充,各有千秋。Ganglia 侧重于收集指标并在一段时间内跟踪它们,而 Nagios 更侧重于作为一种警报机制。因为收集指标和发出警报都是监控的重要方面,所以它们最好结合使用。Ganglia 和 Nagios 都在集群的所有主机上运行代理,并收集信息。

神经中枢

Ganglia 的概念来自加州大学伯克利分校,是一个开源监控项目,旨在用于大型分布式系统。作为集群一部分的每个主机都运行一个名为 gmond 的守护进程,该进程收集并发送指标(如 CPU 使用率、内存使用率等。)从操作系统到中央主机。收到所有指标后,中央主机可以显示、汇总或总结这些指标以备将来使用。

Ganglia 旨在与其他应用程序轻松集成,并收集有关其操作的统计信息。例如,Ganglia 可以轻松地从 Hadoop metrics 接收输出数据,并有效地使用它。gmond(Ganglia 在每台主机上都运行它)占用空间很小,因此可以很容易地在集群中的每台机器上运行,而不会影响用户性能。

Ganglia 的 web 界面(图 3-4 )向您展示了集群使用的硬件、最近一个小时的集群负载、CPU 和内存资源消耗等等。您可以根据需要查看过去一小时、一天、一周或一个月的使用情况摘要。此外,您可以根据需要获得这些资源使用的详细信息。第七章将更详细地讨论神经节。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-4 。Ganglia 监控系统:集群概述

纳吉奥斯

Nagios 提供了一个非常好的警报机制,可以使用 Ganglia 收集的指标。Nagios 的早期版本从其目标主机轮询信息,但目前它使用在主机(集群的一部分)上运行代理的插件。Nagios 有一个优秀的内置通知系统,可以用于通过页面或电子邮件发送某些事件的警报(例如,NameNode 故障或磁盘已满)。Nagios 可以监控应用程序、服务、服务器和网络基础设施。图 3-5 显示了 Nagios web 界面,它可以方便地管理状态(被监控的资源)、警报(在资源上定义)、通知、历史等等。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-5 。用于监控的 Nagios web 界面

Nagios 的真正优势在于数百个用户开发的插件可以免费使用。插件在所有类别中都可用。例如,“系统度量”类别包含子类别“用户”,其中包含诸如“显示用户”之类的插件,这些插件可以在某些用户登录或未登录时向您发出警报。使用这些插件可以减少宝贵的定制时间,这是所有开源(和非开源)软件的主要问题。第七章讨论了设置 Nagios 的细节。

加密:Hadoop 的相关性和实现

作为一个分布式系统,Hadoop 将数据分布在大量主机上,并存储在本地。这些主机之间有大量的数据通信;因此,数据在传输过程中以及在静止和存储在本地存储时都容易受到攻击。Hadoop 最初是一个数据存储库,用于收集 web 使用数据以及其他形式的不敏感的大量数据。这就是为什么 Hadoop 没有任何内置的数据加密功能。

如今,情况正在发生变化,Hadoop 越来越多地被用于在企业中存储敏感的仓库数据。这就产生了对传输中和静态数据进行加密的需求。现在有许多替代方案可以帮助您加密数据。

传输中的数据加密

Hadoop 中的节间通信使用 RPC、TCP/IP、HTTP 等协议。RPC 通信可以使用简单的 Hadoop 配置选项进行加密,并用于 NameNode、JobTracker、DataNodes 和 Hadoop 客户端之间的通信。这使得客户端和 datanode(TCP/IP)之间的文件数据的实际读/写以及 HTTP 通信(web 控制台、NameNode/辅助 NameNode 之间的通信以及 MapReduce shuffle 数据)未加密。

加密 TCP/IP 或 HTTP 通信是可能的,但这需要使用 Kerberos 或 SASL 框架。Hadoop 的当前版本通过在配置文件

core-site.xml

hdfs-site.xml

中设置显式值来允许网络加密(结合 Kerberos)。第四章将重温这个详细的设置,并详细讨论网络加密。

静态数据加密

使用 Hadoop 实现静态加密有许多选择,但它们由不同的供应商提供,并且依赖于他们的发行版来实现加密。最值得注意的是英特尔项目 Rhino(致力于 Apache 软件基金会和开源)和 AWS(亚马逊网络服务)产品,它们为存储在磁盘上的数据提供加密。

因为 Hadoop 通常处理大量数据,加密/解密需要时间,所以所用框架执行加密/解密的速度要足够快,以免影响性能,这一点很重要。英特尔解决方案(即将通过 Cloudera 发行版提供)声称能够以极高的速度执行这些操作——前提是英特尔 CPU 与英特尔磁盘驱动器和所有其他相关硬件配合使用。让我们快速了解一下亚马逊加密“静态”选项的一些细节。

AWS 对存储在 HDFS 中的数据进行加密,并且还支持由其他组件(如 Hive 或 HBase)对加密数据进行操作。这种加密对用户可以是透明的(如果必要的密码存储在配置文件中),或者可以在允许访问敏感数据之前提示用户输入密码,可以逐个文件地应用,并且可以与外部密钥管理应用程序结合使用。这种加密可以使用对称密钥和非对称密钥。要使用这种加密,敏感文件在存储到 HDFS 之前必须使用对称或非对称密钥进行加密。

当加密文件存储在 HDFS 时,它仍然是加密的。根据处理需要对其进行解密,并在移回存储之前重新加密。分析结果也被加密,包括中间结果。数据和结果不会以未加密的形式存储或传输。图 3-6 提供了该过程的概述。存储在 HDFS 的数据使用对称密钥加密,而 MapReduce 作业使用对称密钥(带证书)传输加密数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 3-6 。英特尔 Hadoop 发行版(现为 Project Rhino)提供的静态加密的详细信息

第八章将更详细地介绍加密。它概述了加密概念和协议,然后简要讨论了实现加密的两个选项:使用英特尔的发行版(现在作为 Project Rhino 提供)和使用 AWS 提供透明加密。

摘要

有了路线图,找到你想去的地方并计划如何到达那里就容易多了。本章是您设计和实现 Hadoop 安全性的技术路线图。在概述了 Hadoop 架构之后,您研究了使用 Kerberos 提供安全访问的认证。然后,您学习了如何使用授权来指定访问级别,以及您需要遵循分析数据的多步骤过程,并需要定义有效的授权策略。

为了通过认证和授权来补充您的安全性,您需要持续监控未经授权的访问或不可预见的恶意攻击;Ganglia 或 Nagios 之类的工具会有所帮助。您还了解了使用 Log4j 日志记录系统和 Hadoop 守护进程日志以及审计日志记录对 Hadoop 守护进程的所有访问的重要性。

最后,您了解了传输中(以及静态)的数据加密,以及它作为附加安全级别的重要性,因为这是阻止黑客绕过认证和授权层进行未授权访问的唯一方法。要为 Hadoop 实现加密,可以使用 AWS(亚马逊网络服务)或英特尔的 Project Rhino 的解决方案。

在本书的其余部分,你将遵循这个路线图,深入探讨本章中出现的每个主题。我们将在第四章中从认证开始。

四、Hadoop 中的开源认证

在前面的章节中,您了解了什么是安全系统,以及与业界认为的安全系统 Microsoft SQL Server(关系数据库系统)相比,Hadoop 安全性缺失了什么。本章将着重于实现安全系统的一些特性,以保护您的 Hadoop 集群免受所有大灰狼的攻击。微调安全性与其说是科学,不如说是艺术。对于一个环境来说,没有什么规则是“刚刚好”的,但是你可以依靠一些基本的约定来帮助你更接近——如果不是“刚刚好”的话例如,由于 Hadoop 是一个分布式系统,主要通过 Windows PC 上的客户端软件进行访问,因此从保护客户端开始是有意义的。接下来,您可以考虑通过添加强身份认证来保护 Hadoop 集群,等等。

然而,在你衡量成功之前,你需要一个标准。在这种情况下,您需要一个理想的 Hadoop 安全设置的愿景。您将在下一节中找到详细信息。

安全拼图的碎片

图 4-1 显示了一个 Hadoop 广泛安全设置的例子。它始于一个安全的客户端。SSH 协议使用密钥对保护客户端;服务器使用公钥,客户端使用私钥。这是为了对抗欺骗(拦截并重定向到攻击者系统的连接)以及黑客攻击或泄露的密码。在接下来的“建立安全的客户端访问”一节中,您将更深入地研究安全客户端设置的细节。在 Hadoop 系统允许访问之前,它使用 Kerberos(一种用于认证的开源应用程序)对客户端进行认证。在“构建安全的用户认证”一节中,您将了解如何设置 Kerberos 并使其与 Hadoop 一起工作。

一旦用户被连接,重点是根据用户的角色限制权限。图 4-1 中的用户可以访问除敏感的薪资数据之外的所有用户数据。通过将数据分成多个文件并为它们分配适当的权限,可以很容易地实现这一点。第五章关注这些授权问题及更多。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-1 。理想的 Hadoop 安全性,具备所有必需的组件

您还将观察到各种 Hadoop 进程之间(例如 NameNode 和 DataNodes 之间)的进程间通信是安全的,这对于分布式计算环境是至关重要的。这样的环境涉及各种主机之间的大量通信,并且不安全的数据容易受到各种类型的恶意攻击。本章的最后一节探讨了如何保护或加密 Hadoop 中的进程间流量。

这些是 Hadoop 安全难题的主要部分。缺少的一部分是静态数据的加密,但是您将在第八章中了解更多。

建立安全的客户端访问

对 Hadoop 集群的访问从您使用的客户端开始,因此从保护客户端开始。不安全的数据容易受到恶意攻击,这可能导致数据被破坏或窃取用于非法用途。对于数据块分布在大量节点上的分布式系统(如 Hadoop ),这种危险更大。客户端就像是实际数据的网关。在你考虑保护房子之前,你需要保护大门。

OpenSSH 或 SSH 协议通常用于通过使用登录/密码或访问密钥来保护客户端。密钥是更好的选择,因为密码可能被泄露、破解或伪造。对于基于 Windows 和基于 Linux 的客户端来说,PuTTY (

www.chiark.greenend.org.uk/~sgtatham/putty

)都是支持 SSH 协议的优秀开源客户端。除了免费之外,PuTTY 的一个主要优势是它允许使用密钥和密码短语而不是密码进行访问的能力。PuTTY 有一个不太明显但同样重要的额外好处,那就是帮助对抗欺骗,这值得你关注。

用 PuTTY 的主机密钥对抗欺骗

正如您所记得的,欺骗是一种用于提取您的个人信息(如密码)以备滥用的技术,通过将您的连接重定向到攻击者的计算机(而不是您认为您所连接的计算机),从而将您的密码发送到攻击者的计算机。利用这种技术,攻击者可以访问您的密码、登录并使用您的帐户来达到他们自己的恶意目的。

为了对抗欺骗,一个独特的代码(称为主机密钥 ) 被分配给每个服务器。创建这些密钥的方式是,一个服务器不可能伪造另一个服务器的密钥。因此,如果您连接到一个服务器,它向您发送了一个不同的主机密钥(与您预期的不同),SSH(或者像 PuTTY 这样使用 SSH 的安全客户端)可以警告您您连接到了一个不同的服务器,这可能意味着正在进行欺骗攻击!

PuTTY 通过 Windows 注册表中的条目存储主机密钥(对于您成功连接的服务器)。然后,下次连接到以前连接过的服务器时,PuTTY 会将服务器提供的主机密钥与上次存储在注册表中的密钥进行比较。如果不匹配,您将看到一个警告,然后有机会在您提供密码或任何其他私人信息之前放弃您的连接。

然而,当您第一次连接到服务器时,PuTTY 无法检查主机密钥是否正确。因此它会发出一个警告,询问您是否想要信任这个主机密钥:

The server's host key is not cached in the registry. You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 10245c:d4:6f:b7:f8:e9:57:32:3d:a3:3f:cf:6b:47:2c:2a
If you trust this host, hit Yes to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, hit No.
If you do not trust this host, hit Cancel to abandon the
connection.

如果您不知道该主机,或者您对该主机是否是您想要连接的主机有任何疑问,您可以取消连接,以避免成为欺骗的受害者。

使用 PuTTY 的基于密钥的认证

假设一个超级黑客进入了您的网络,并获得了从您的客户端到您希望连接的服务器的通信。假设这个黑客捕获了真实主机发送给你的客户端的主机认证字符串,并把它作为自己的字符串返回,让你连接到他的服务器,而不是真实的服务器。现在,他可以很容易地获得您的密码,并使用该密码访问敏感数据。

你如何能阻止这样的攻击?答案是用 基于密钥的认证代替密码。没有公钥,黑客就无法访问!

实现认证密钥的一种方法是使用 SSH,SSH 是一种用于通过公共通道或公共的不安全网络进行安全通信的协议。通信的安全性依赖于用于数据加密和解密的密钥对。SSH 可以以多种方式使用(或实现)。您可以自动生成公钥/私钥对来加密网络连接,然后使用密码验证来登录。使用 SSH 的另一种方法是手动生成一个公钥/私钥对来执行认证,这将允许用户或程序在不指定密码的情况下登录。

对于基于 Windows 的客户端,可以使用 PuTTYgen 生成密钥对,PuTTYgen 是开源的,可以免费获得。密钥对由复制到服务器的公钥和位于安全客户端的私钥组成。

私钥可以用来生成新的签名。没有私钥的任何人都无法伪造用私钥生成的签名。然而,拥有相应公钥的人可以检查特定签名是否真实。

当使用密钥对进行认证时,PuTTY 可以使用您的私钥(使用密钥文件指定)生成签名。服务器可以检查签名是否真实(使用您的公钥),并允许您登录。如果您的客户端被欺骗,攻击者截获的只是一个无法重用的签名,但您的私钥或密码不会被泄露。图 4-2 说明了认证过程。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-2 。使用 PuTTY 的基于密钥的认证

要使用 PuTTY 设置基于密钥的认证,您必须首先选择所需的密钥类型。例如,我将使用 RSA 并设置一个可以用于 Hadoop 集群的密钥对。要设置密钥对,打开 PuTTY 密钥生成器(

PuTTYgen.exe

)。在窗口底部,在生成密钥之前选择参数。例如,要生成用于 SSH-2 协议的 RSA 密钥,选择密钥类型下的 SSH-2 RSA 以生成。生成的密钥中的位数的值决定了密钥的大小或强度。对于这个例子,1024 就足够了,但是在现实世界中,为了更好的安全性,您可能需要一个更长的密钥,比如 2048。需要记住的重要一点是,密钥越长越安全,但是加密/解密处理时间会随着密钥长度的增加而增加。输入一个密钥密码(为了保护您的私钥而加密)并记下它,因为您稍后需要使用它来解密。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传注意可用于 PuTTY 的最常见的公钥算法是 RSA 和 DSA。PuTTY 开发者强烈推荐你使用 RSADSA(也称为 DSS,美国的联邦数字签名标准)有一个固有的弱点,即可以轻松创建包含足够信息的签名,从而泄露私有密钥。(为了更好的理解为什么 RSA 几乎不可能被破解,参见第八章。)

接下来,点击生成按钮。作为回应,PuTTYgen 让你四处移动鼠标来产生随机性(那是 PuTTYgen 开发者在跟我们开玩笑!).在“关键点”窗口的空白区域上绕圈移动鼠标;进度条会随着 PuTTYgen 收集到足够的随机性并生成密钥而逐渐填满,如图图 4-3 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-3 。生成用于实现安全客户端的密钥对

生成密钥后,点击保存公钥保存私钥按钮保存密钥。

接下来,您需要将公钥复制到位于您试图连接的服务器上的

home

目录下的

.ssh

目录中的文件

authorized_keys

。为此,请参见图 4-3 中公钥粘贴到打开的 SSH authorized_keys 文件部分。将光标移动到该部分并复制所有文本(如图所示)。然后,打开一个 PuTTY 会话,使用您的登录名和密码进行连接。转到目录

.ssh

,用你选择的编辑器打开

authorized_keys

文件。将使用 PuTTYgen 创建的公钥文本粘贴到文件中,并保存文件(图 4-4 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-4 。在

authorized_keys

文件中粘贴公钥

使用密码短语

如果有人进入了你的电脑会怎么样?他们可以像您一样生成签名。然后,他们可以使用您的凭据轻松连接到您的 Hadoop 集群!这当然可以通过使用您选择的的密码在存储到您的本地机器之前加密您的私钥来轻松避免。然后,为了生成签名,PuTTY 将需要解密密钥,这将需要您的密码,从而防止任何未经授权的访问。

现在,无论何时登录都需要输入密码短语,这很不方便。因此,Putty 提供了 Pageant,这是一个认证代理,它存储解密的私钥,并根据请求使用它们来生成签名。你所需要做的就是开始 Pageant 并输入你的私钥和密码。然后,您可以任意次数调用 PuTTY Pageant 会自动生成签名。这种安排将一直有效,直到您重新启动 Windows 客户端。Pageant 的另一个很好的特性是,当它关闭时,它永远不会将您解密的私钥存储在您的本地磁盘上。

因此,作为最后一步,配置您的 PuTTY 客户端使用私钥文件而不是密码进行认证(图 4-5 )。点击选项 SSH 旁边的 + 打开下钻,然后点击该选项下的选项 Auth (授权)。浏览并选择您之前保存的私钥文件(通过 PuTTYgen 生成)。点击打开打开新的会话。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-5 。使用 PuTTY 进行私钥认证的配置选项

现在你已经准备好通过服务器使用登录和密码进行认证,如图 4-6 中的所示。在登录提示符下输入登录名(本例中为

root

),并输入密码进行连接!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-6 。使用登录名和密码进行安全认证

在某些情况下(例如,预定的批处理),不可能键入密码短语;在这种情况下,你可以输入一次密码,启动 Pageant 并加载你的私钥。请参考附录 A 中关于 Pageant 使用和实现的示例,以及附录 B 中关于基于 Linux 的客户端的 PuTTY 实现。

构建安全的用户认证

安全的客户端连接至关重要,但这只是一个好的起点。当这个安全客户端连接到您的 Hadoop 集群时,您需要保护它。用户安全过程从认证用户开始。虽然 Hadoop 本身没有认证用户的方法,但是目前所有主要的 Hadoop 发行版都可以安装 Kerberos,并且 Kerberos 提供了认证。

对于早期版本的 Hadoop,当用户试图访问 Hadoop 集群时,Hadoop 只需检查 ACL 以确保底层操作系统用户被允许访问,然后提供这种访问。这不是一个非常安全的选项,也没有限制用户的访问(因为用户可以很容易地模拟 Hadoop 超级用户)。然后,用户可以访问 Hadoop 集群中的所有数据,并可以根据需要修改或删除这些数据。因此,您需要配置 Kerberos 或另一个类似的应用程序,在允许访问数据之前对用户进行认证——当然,还要限制访问!

Kerberos 是 Hadoop 用于认证的最流行的选项之一。Kerberos 是由麻省理工学院开发的,自 20 世纪 80 年代以来一直存在,并经过多次增强。目前的版本 Kerberos 是在 1993 年设计的,可以作为开源下载免费获得。Kerberos 最常用于保护 Hadoop 集群和提供安全的用户认证。在本节中,您将了解 Kerberos 是如何工作的,它的主要组件是什么,以及如何安装它。安装之后,我将讨论 Hadoop 的一个简单的 Kerberos 实现。

Kerberos 概述

Kerberos 是一种用于“不可信网络上的可信主机”的认证协议这仅仅意味着 Kerberos 假设它与之通信的所有主机都是可信的,并且不涉及欺骗或者它使用的密钥没有被泄露。为了更有效地使用 Keberos,请考虑其他几个关键事实:

  • Kerberos 一直依赖于中央服务器。如果中央服务器不可用,任何人都无法登录。可以使用多个“中央”服务器(以降低风险)或额外的认证机制(作为后备)。
  • Kerberos 非常依赖于时间,因此所有受控主机的时钟必须在配置的限制范围内保持同步(默认为 5 分钟)。大多数情况下,网络时间协议守护程序有助于保持受控主机的时钟同步。
  • Kerberos 提供了单点登录方法。客户只需要在每次会话中提供一次密码,然后就可以透明地访问所有授权服务。
  • 密码不应保存在客户端或任何中间应用服务器上。Kerberos 将它们集中存储,没有任何冗余。

图 4-7 提供了 Kerberos 认证架构的概述。如图所示,认证服务器和票据授予服务器是 Kerberos 密钥分发中心的主要组件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4-7 。Kerberos 密钥分发中心及其主要组件(TGT =票证授予票证)

客户端使用 Kerberos 客户端库请求访问启用 Kerberos 的服务。Kerberos 客户端联系 Kerberos 分发中心或 KDC(托管凭证数据库的中央 Kerberos 服务器)并请求访问。如果提供的凭据有效,KDC 将提供请求的访问权限。KDC 使用一个内部数据库来存储凭证,以及两个主要组件:认证服务器(AS)和票据授予服务器(TGS)。

证明

Kerberos 认证过程包含三个主要步骤:

  1. AS 向用户(和主机)授予票据授予票据(TGT)作为认证令牌。TGT 仅在特定时间内有效(有效性由管理员通过配置文件进行配置)。在服务原则(用于运行服务或后台进程的登录)请求 TGT 的情况下,凭证通过名为 keytabs 的特殊文件提供给 AS。
  2. 客户端使用凭证解密 TGT,然后使用 TGT 从票证授予服务器获取服务票证,以访问“Kerberos 化”的服务。一个客户端可以对多个 TGS 请求使用同一个 TGT(直到 TGT 过期)。
  3. 用户(和主机)使用服务票来验证和访问特定的支持 Kerberos 的服务。

重要术语

要完全理解 Kerberos,您需要使用它的领域、主体、票据和数据库语言。举一个 Kerberos 实现的例子,您正在名为

pract_hdp_sec

的单个节点集群上实现 Kerberos,并且您正在使用名为

EXAMPLE.COM

的虚拟域或领域。

术语表示用于认证的管理域(类似于 Windows 域)。其目的是建立虚拟边界,供 AS 用来对用户、主机或服务进行认证。这并不意味着用户和服务之间的认证强制他们在同一个领域中!如果两个对象属于不同的领域,但它们之间有信任关系,那么认证仍然可以进行(称为交叉认证 )。对于我们的实现,我创建了一个名为

EXAMPLE.COM

的领域(注意,按照惯例,一个领域通常使用大写字母)。

主体是与领域相关联的用户、主机或服务,并作为条目存储在通常位于 KDC 的 as 数据库中。Kerberos 5 中的主体使用以下格式定义:

Name[/Instance]@REALM

用户常用的用法是用户名

@

领域用户名

/

角色

@

领域(例如

alex/admin@REALM

alex@REALM

可能是两个不同的主体)。对于服务主体,常见的格式是服务

/

主机名

@

领域(例如

hdfs/host1.myco.com

)。注意,Hadoop 期望它的服务主体有一个特定的格式。对于我们的实现,我定义了一些原则,比如

hdfs/[email protected]

(NameNode 和 DataNode 的

hdfs

),

mapred/[email protected]

(JobTracker 和 TaskTracker 的

mapred

)等等。

是客户端请求认证时由 AS 生成的令牌。票证中的信息包括:请求用户的主体(通常是用户名)、服务的主体、客户端的 IP 地址、有效日期和时间(以时间戳格式)、票证的最大生命周期和会话密钥(这具有基本的作用)。每个票证通常在 24 小时后过期,尽管这对于给定的 Kerberos 安装是可配置的。

此外,票据可以由用户请求更新,直到从发行开始的可配置的时间段(例如,从发行开始的 7 天)。如果系统管理员已经将登录客户端(例如 SSH)配置为在登录时自动获得票据,则用户可以明确地使用 Kerberos 客户端来获得票据,或者被自动提供一个票据。服务通常使用 keytab 文件(包含服务密码的受保护文件)来运行后台线程,这些线程根据需要获取和更新服务的 TGT。所有 Hadoop 服务都需要一个 keytab 文件放在各自的主机上,这个文件的位置在服务站点 XML 中定义。

Kerberos 使用一个加密的数据库 来存储所有与用户和服务相关的主体条目。每个条目包含以下信息:主体名称、加密密钥、与主体相关联的票证的最大有效期、与主体相关联的票证的最大续订时间、密码到期日期以及主体的到期日期(在此之后将不会颁发任何票证)。

还有更多与 Kerberos 架构相关的细节,但是因为本章主要关注为 Hadoop 安装和配置 Kerberos,所以对 Kerberos 架构的基本理解将满足我们的目的。所以让我们从 Kerberos 安装开始。

安装和配置 Kerberos

安装 Kerberos 的第一步是为您的新 KDC 安装所有 Kerberos 服务。对于 Red Hat Enterprise Linux (RHEL)或 CentOS 操作系统,使用以下命令:

yum install krb5-server krb5-libs krb5-auth-dialog krb5-workstation

安装服务器后,您必须编辑两个主要配置文件,缺省情况下,它们位于以下目录中(如果没有,请使用 Linux 实用程序“find”找到它们):

  • /etc/krb5.conf
  • /var/kerberos/krb5kdc/kdc.conf

下一步是指定您的领域(例如

EXAMPLE.COM

),并将 KDC 值更改为完全合格的 Kerberos 服务器主机的名称(这里是

pract_hdp_sec

)。您还必须将

/etc/krb5.conf

的更新版本复制到集群中的每个节点。下面是我们的例子中的

/etc/krb5.conf

:

[logging]
 default = FILE:/var/log/krb5libs.log
 kdc = FILE:/var/log/krb5kdc.log
 admin_server = FILE:/var/log/kadmind.log

[libdefaults]
 default_realm = EXAMPLE.COM
 dns_lookup_realm =false
 dns_lookup_kdc =false
 ticket_lifetime =24h
 renew_lifetime =7d
 forwardable =true[kdc]
profile =/var/kerberos/krb5kdc/kdc.conf

[realms]
 EXAMPLE.COM ={
  kdc = pract_hdp_sec
  admin_server = pract_hdp_sec
 }[domain_realm].example.com = EXAMPLE.COM
  example.com = EXAMPLE.COM

请注意领域名称和 KDC 名称的更改值。示例票证在创建后的 24 小时内有效,因此

ticket_lifetime

被设置为

24h

。7 天后这些票可以续签,因为

renew_lifetime

被设置为

7d

。以下是我正在使用的

/var/kerberos/krb5kdc/kdc.conf

:

[kdcdefaults]
 kdc_ports =88
 kdc_tcp_ports =88[realms]
 EXAMPLE.COM ={
  profile =/etc/krb5.conf
  supported_enctypes = aes128-cts:normal des3-hmac-sha1:normal
arcfour-hmac:normal des-hmac-sha1:normal des-cbc-md5:normal des-cbc-crc:normal
allow-null-ticket-addresses =true
database_name =/var/Kerberos/krb5kdc/principal
#master_key_type = aes256-cts
  acl_file =/var/kerberos/krb5kdc/kadm5.acl
  admin_keytab =/var/kerberos/krb5kdc/kadm5.keytab
  dict_file =/usr/share/dict/words
  max_life =2d0h 0m 0s
  max_renewable_life =7d0h 0m 0s
  admin_database_lockfile =/var/kerberos/krb5kdc/kadm5_adb.lock
  key_stash_file =/var/kerberos/krb5kdc/.k5stash
  kdc_ports =88
  kadmind_port =749
  default_principle_flags =+renewable
}

在领域

EXAMPLE.COM

的设置中,

acl_file

参数指定 ACL(RHEL 或 CentOS 中的文件

/var/kerberos/krb5kdc/kadm5.acl

),用于定义对 Kerberos 数据库具有管理(修改)访问权限的主体。该文件可以简单到只有一个条目:

*/[email protected]*

这个条目指定所有具有

/admin

实例扩展的主体对数据库具有完全访问权限。Kerberos 服务

kadmin

需要重新启动才能使更改生效。

此外,请注意

max_life

(最长票证寿命)设置对于领域

EXAMPLE.COM

2d

(2 天)。您可以覆盖特定领域的配置设置。您也可以为主体指定这些值。

注意,在前面代码的

[realms]

部分,我已经禁用了 256 位加密。如果要使用 256 位加密,必须下载 Java Cryptography Extension(JCE),并按照说明将其安装在任何运行使用 Kerberos 的 Java 进程的节点上(对于 Hadoop,所有集群节点)。如果您想跳过这一步,只使用 128 位加密,在生成您的 KDC 主密钥之前,删除行

#master_key_type = aes256-cts

并删除对

aes-256

的引用,如“创建数据库”一节所述

这包括安装和设置 Kerberos。请注意,不可能涵盖所有可能的选项(操作系统、版本等。)和 Kerberos 安装的细微差别。关于 Kerberos 安装的更多讨论,请参考麻省理工学院的 Kerberos 安装指南。奥莱利的 Kerberos:权威指南也是一个很好的参考。

回到 Kerberos 实现,让我创建一个数据库并设置主体(用于 Hadoop)。

为 Kerberos 实现做准备

Kerberos 使用内部数据库(存储为文件)来保存为使用而设置的主体的详细信息。该数据库包含用户(主体)及其私钥。主体包括 Kerberos 使用的内部用户以及您定义的用户。数据库文件存储在配置文件

kdc.conf

文件中定义的位置;对于这个例子,

/var/kerberos/krb5kdc/principal.

创建数据库

要设置数据库,请使用实用程序 kdb5_util:

kdb5_util create -r EXAMPLE.COM –s

您将会看到类似这样的响应:

Loading random data
Initializing database '/var/kerberos/krb5kdc/principal'for realm 'EXAMPLE.COM',
master key name 'K/[email protected]'
You will be prompted for the database Master Password.
It is important that you NOT FORGET this password.
Enter KDC database master key:
Re-enter KDC database master key to verify:

请记下万能钥匙。另外,请注意

-s

选项允许您将数据库的主服务器密钥保存在隐藏文件中(使用

kdc.conf

中的参数

key_stash_file

定义)。如果 stash 文件不存在,您需要在每次启动时使用主密码(在安装过程中指定)登录 KDC。这将自动重新生成主服务器密钥。

既然已经创建了数据库,那么就创建第一个用户主体。这必须在 KDC 服务器上完成,同时您以

root

身份登录:

/usr/sbin/kadmin.local -q "addprinc root/admin"

系统将提示您输入密码。请记下委托人

root/[email protected]

的密码。您可以稍后创建其他主体;现在,是时候开始 Kerberos 了。要为 RHEL 或 CentOS 操作系统执行此操作,请发出以下命令来启动 Kerberos 服务(对于其他操作系统,请参考相应的命令参考):

/sbin/service kadmin start
/sbin/service krb5kdc start

创建服务主体

接下来,我将使用 kadmin 实用程序创建用于 Hadoop 的服务主体。主要名称

hdfs

将用于 HDFS;

mapred

将用于 MapReduce,

HTTP

用于 HTTP,

yarn

用于 YARN 相关的服务(在这段代码中,

kadmin:

是提示;命令以粗体显示):

[root@pract_hdp_sec]# kadmin
Authenticating as principal root/[email protected].
Password for root/[email protected]:
kadmin:  addprinc -randkey hdfs/[email protected]
Principal "hdfs/[email protected]" created.
kadmin:  addprinc -randkey mapred/[email protected]
Principal "mapred/[email protected]" created.
kadmin:  addprinc -randkey HTTP/[email protected]
Principal "HTTP/[email protected]" created.
kadmin:  addprinc -randkey yarn/[email protected]
Principal "yarn/[email protected]" created.
kadmin:

创建 Keytab 文件

Keytab 文件用于以非交互方式验证服务。因为您可以安排服务远程运行或在特定时间运行,所以您需要将认证信息保存在一个文件中,以便可以与 Kerberos 内部数据库进行比较。Keytab 文件用于此目的。

回到文件创建,提取相关的 keytab 文件(使用 kadmin)并将其放在各个组件的 keytab 目录(

/etc/security/keytabs

)中(

kadmin:

)是提示;命令以粗体显示):

[root@pract_hdp_sec]# kadmin
Authenticating as principal root/[email protected].
Password for root/[email protected]:
kadmin: xst -k mapred.keytab hdfs/[email protected] HTTP/[email protected]
Entry for principal hdfs/[email protected], encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/[email protected], encryption type des3-cbc-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/[email protected], encryption type arcfour-hmac added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/[email protected], encryption type des-hmac-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal hdfs/[email protected], encryption type des-cbc-md5 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/[email protected], encryption type aes128-cts-hmac-sha1-96 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/[email protected], encryption type des3-cbc-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/[email protected], encryption type arcfour-hmac added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/[email protected], encryption type des-hmac-sha1 added to keytab WRFILE:mapred.keytab.
Entry for principal HTTP/[email protected], encryption type des-cbc-md5 added to keytab WRFILE:mapred.keytab.

请注意,所有受支持加密类型的密钥条目(在配置文件

kdc.conf

中定义为参数

supported_enctypes

)都被添加到主体的 keytab 文件中。

回到 keytab 创建,为其他主体创建 keytab 文件(在 kadmin 提示符下),如下所示:

kadmin:xst -k mapred.keytab hdfs/[email protected] http/[email protected]
kadmin:xst -k yarn.keytab hdfs/[email protected] http/[email protected]

您可以使用

klist

命令验证正确的 keytab 文件和主体是否与正确的服务相关联。例如,在 NameNode 上:

[root@pract_hdp_sec]# klist -kt mapred.keytab
Keytab name: FILE:mapred.keytab
KVNO Timestamp Principal
-----------------------------------------------------------------------------510/18/1412:42:21 hdfs/[email protected]/18/1412:42:21 hdfs/[email protected]/18/1412:42:21 hdfs/[email protected]/18/1412:42:21 hdfs/[email protected]/18/1412:42:21 hdfs/[email protected]/18/1412:42:21 HTTP/[email protected]/18/1412:42:21 HTTP/[email protected]/18/1412:42:21 HTTP/[email protected]/18/1412:42:21 HTTP/[email protected]/18/1412:42:21 HTTP/[email protected]

到目前为止,您已经为 HDFS、MapReduce 和 YARN 相关的主体定义了主体并提取了 keytab 文件。您将需要遵循相同的过程,并为运行在您的 Hadoop 集群上的任何其他组件服务(如 Hive、HBase、Oozie 等)定义主体。注意,web 通信的主体必须命名为

HTTP

,因为使用 Kerberos 的基于 web 的协议实现需要这个命名。

要将 keytab 文件部署到从节点,请将 keytab 文件复制(或移动,如果是新创建的)到

/etc/hadoop/conf

文件夹。您需要保护 keytab 文件(只有所有者可以看到此文件)。因此,您需要将所有者更改为访问 keytab 的服务用户名(例如,如果 HDFS 进程作为用户

hdfs

运行,那么用户

hdfs

应该拥有 keytab 文件)并设置文件权限 400。请记住,

hdfs

mapred

http

的服务主体有一个与用户名相关联的 FQDN(完全合格域名)。此外,服务主体是特定于主机的,对于每个节点都是唯一的。

[root@pract_hdp_sec]# sudo mv hdfs.keytab mapred.keytab /etc/hadoop/conf/[root@pract_hdp_sec]# sudo chown hdfs:hadoop /etc/hadoop/conf/hdfs.keytab
[root@pract_hdp_sec]# sudo chown mapred:hadoop /etc/hadoop/conf/mapred.keytab
[root@pract_hdp_sec]# sudo chmod 400/etc/hadoop/conf/hdfs.keytab
[root@pract_hdp_sec]# sudo chmod 400/etc/hadoop/conf/mapred.keytab

为 Hadoop 实现 Kerberos

到目前为止,我已经安装并配置了 Kerberos,还创建了数据库、主体和 keytab 文件。那么,对 Hadoop 使用这种认证的下一步是什么呢?我需要将 Kerberos 设置信息添加到相关的 Hadoop 配置文件中,并将之前设置的 Kerberos 主体映射到操作系统用户(因为操作系统用户将用于实际运行 Hadoop 服务)。我还需要假设一个处于非安全模式的 Hadoop 集群已经配置好并且可用。总而言之,为 Kerberos 配置 Hadoop 将分两个阶段完成:

  • 将服务主体映射到其操作系统用户名
  • 向各种 Hadoop 配置文件添加信息

将服务主体映射到其操作系统用户名

规则用于将服务主体映射到它们各自的操作系统用户名。这些规则在 Hadoop 配置文件

core-site.xml

中被指定为可选键

hadoop.security.auth_to_local

的值。

默认规则简单地命名为

DEFAULT

。它将默认域中的所有主体转换为它们的第一个组件。例如,

[email protected]

hdfs/[email protected]

都变成了

hdfs

,假设你的默认域或领域是

EXAMPLE.COM

。因此,如果服务主体和操作系统用户名相同,默认规则就足够了。如果两个名称不相同,您必须创建规则来进行映射。

每个规则分为三个部分:基本、过滤和替换。 base 首先指定主体名称(不包括领域)中的组件数量,然后是一个冒号,以及从主体名称的各个部分构建用户名的模式。在模式部分中,

$0

翻译成领域,

$1

翻译成第一个组件,

$2

翻译成第二个组件。例如,

[2:$1]

hdfs/[email protected]

翻译成

hdfs

过滤器由括号中的正则表达式组成,该表达式必须与要应用的规则所生成的字符串相匹配。例如,(

.*@EXAMPLE.COM

)匹配任何以

@EXAMPLE.COM

结尾的字符串。

替换是一个 sed(流行的 Linux 流编辑器)规则,它将正则表达式转换成固定的字符串。例如:

s/@[A-Z]*\.COM//

删除

@

的第一个实例,后面跟一个大写字母名称,后面跟

.COM

在我的例子中,我使用操作系统用户

hdfs

来运行 NameNode 和 DataNode 服务。因此,如果我创建了 Kerberos 主体

nn/[email protected]

dn/[email protected]

用于 Hadoop,那么我需要将这些主体映射到 os 用户

hdfs

。为此目的的规则是:

RULE:[2:$1@$0]([nd]n@.*EXAMPLE.COM) s/.*/hdfs/

向各种 Hadoop 配置文件添加信息

要使 Kerberos 能够与 HDFS 一起工作,您需要修改两个配置文件:

  • core-site.xml
  • hdfs-site.xml

表 4-1 显示了

core-site.xml

内属性的修改。请记住将这些更改传播到集群中的所有主机。

表 4-1 。修改 Hadoop 配置文件

core-site.xml

中的属性

|

属性名称

|

属性值

|

描述

|
| — | — | — |
|

hadoop.security.authentication

|

kerberos

| 设置群集的认证类型。有效值为

simple

(默认值)或

Kerberos

。 |
|

hadoop.security.authorization

|

true

| 为不同的协议启用授权 |
|

hadoop.security.auth_to_local

|

[2:$1]``DEFAULT

| 使用映射规则从 Kerberos 主体名称到本地 os 用户名的映射 |
|

hadoop.rpc.protection

|

privacy

| 可能的值有

authentication

integrity

privacy

authentication

=相互客户端/服务器认证

integrity

=认证和完整性;保证客户端和服务器之间交换的数据以及认证的完整性

privacy

=认证、完整性和保密性;加密客户端和服务器之间交换的数据 |

hdfs-site.xml

配置文件指定了 keytab 位置以及各种 HDFS 守护进程的主体名称。请记住,

hdfs

http

主体是特定于特定节点的。

Hadoop 集群可能包含大量的 DataNodes,实际上不可能为每个 DataNodes 手动配置主体。因此,Hadoop 提供了一个在运行时解析为完全限定域名的

_HOST

变量。该变量允许站点 XML 在整个集群中保持一致。但是,请注意

_HOST

变量不能用于所有的 Hadoop 配置文件。比如 Zookeeper 使用的

jaas.conf

文件(它提供了跨集群节点的资源同步,应用程序可以使用它来确保跨集群的任务是序列化或同步的)和 Hive 不支持

_HOST

变量。表 4-2 显示了对

hdfs-site.xml

中属性的修改,其中一些使用了

_HOST

变量。请记住将这些更改传播到集群中的所有主机。

表 4-2 。修改了 Hadoop 配置文件

hdfs-site.
xml

的属性

|

属性名称

|

属性值

|

描述

|
| — | — | — |
|

dfs.block.access.token.enable

|

True

| 如果为 true,则访问令牌用于访问 DataNodes |
|

dfs.namenode.kerberos. principal

|

hdfs/_HOST@

EXAMPLE.COM | NameNode 的 Kerberos 主体名称 |
|

dfs.secondary.namenode. kerberos.principal

|

hdfs/_HOST @

EXAMPLE.COM | 辅助 NameNode 服务器的地址 |
|

*dfs.secondary.https.port

|

50490

| 辅助 NameNode 绑定到的 https 端口 |
|

dfs.web.authentication.kerberos. principal

|

HTTP/_HOST

@例。COM | Hadoop 使用的 Kerberos 主体 |
|

dfs.namenode.kerberos.``internal.spnego.``principal

|

HTTP/_HOST

@例。COM | 这是

http

校长对于 HTTP 服务 |
|

dfs.secondary.namenode.``kerberos.internal.``spnego.principal

|

HTTP/_HOST

@例。COM | 这是

http

校长对于 http 服务 |
|

*dfs.secondary.http.address

|

192.168.142.135:50090

| 辅助 NameNode 主机的 IP 地址和端口 50090 |
|

dfs.web.authentication. kerberos.keytab

|

/etc/hadoop/conf/spnego.service.keytab

| 带有

http

主体凭证的 Kerberos keytab 文件 |
|

dfs.datanode.kerberos.principal

|

hdfs/_HOST

@例。COM | 运行 DataNode 的 Kerberos 主体 |
|

dfs.namenode. keytab.file

|

/etc/hadoop/conf/``hdfs.keytab

| 包含 NameNode 服务和主机主体的 keytab 文件 |
|

dfs.secondary.namenode. keytab.file

|

/etc/hadoop/conf/``hdfs.keytab

| 包含 NameNode 服务和主机主体的 keytab 文件 |
|

dfs.datanode. keytab.file

|

/etc/hadoop/conf/``hdfs.keytab

| DataNode 的 keytab 文件 |
|

*dfs.https.port

|

50470

| NameNode 绑定到的 https 端口 |
|

*dfs.https.address

|

192.168.142.135:50470

| NameNode 的 https 地址(主机的 IP 地址+端口 50470) |
|

dfs.datanode.address

|

0.0.0.0:1019

| 用于数据传输的 DataNode 服务器地址和端口。 |
|

dfs.datanode.http.address

|

0.0.0.0:1022

| DataNode http 服务器地址和端口 |

  • 这些值可能会因集群而异

文件

core-site.xml

hdfs-site.
xml

包含在下载中供您参考。它们还包含为其他组件(如 Hive、Oozie 和 HBase)设置的 Kerberos 相关属性。

MapReduce 相关配置

对于 MapReduce(版本 1),

mapred-site.xml

文件需要配置为与 Kerberos 一起工作。它需要指定 keytab 文件的位置以及 JobTracker 和 TaskTracker 守护程序的主体名称。使用表 4-3 作为指南,记住

mapred

原则是特定于特定节点的。

表 4-3 。

mapred

校长

|

属性名称

|

属性值

|

描述

|
| — | — | — |
|

mapreduce.jobtracker.``kerberos.principal

|

mapred/_HOST

@例。COM |

mapred

用于启动 JobTracker 守护程序的主体 |
|

mapreduce.jobtracker.``keytab.file

|

/etc/hadoop/conf/mapred.keytab

|

mapred

用户的 keytab 文件的位置 |
|

mapreduce.tasktracker.``kerberos.principal

|

mapred/_HOST

@例。COM |

mapred

用于启动 TaskTracker 守护程序的主体 |
|

mapreduce.tasktracker.``keytab.file

|

/etc/hadoop/conf/mapred.keytab

|

mapred

用户的 keytab 文件的位置 |
|

mapred.task.tracker.``task-controller

|

org.apache.``hadoop.mapred.``LinuxTaskController

|

TaskController

用于启动子 JVM 的类 |
|

mapreduce.tasktracker.group

|

mapred

| 运行 TaskTracker 的组 |
|

mapreduce.jobhistory.keytab

|

/etc/hadoop/conf/``mapred.keytab

|

mapred

用户的 keytab 文件的位置 |
|

mapreduce.jobhistory.principal

|

mapred/_HOST

@例。COM |

mapred

用于启动作业历史守护程序的主体 |

对于 YARN,需要配置

yarn-site.xml

文件来指定 keytab 和 principal details 表 4-4 保存了详细信息。

表 4-4 。纱校长

|

属性名称

|

属性值

|

描述

|
| — | — | — |
|

yarn.resourcemanager.principal

|

yarn/_HOST

@例。COM |

yarn

用于启动资源管理器守护程序的主体 |
|

yarn.resourcemanager.keytab

|

/etc/hadoop/conf/yarn.keytab

|

yarn

用户的 keytab 文件的位置 |
|

yarn.nodemanager.principal

|

yarn/_HOST

@例。COM |

yarn

用于启动节点管理器守护进程的主体 |
|

yarn.nodemanager.keytab

|

/etc/hadoop/conf/yarn.keytab

|

yarn

用户的 keytab 文件的位置 |
|

yarn.nodemanager.container-executor.class

|

org.apache.hadoop.yarn.server.nodemanager.``LinuxContainerExecutor

| 用于在

yarn

中启动应用程序的执行器类 |
|

yarn.nodemanager.linux-containerexecutor.group

|

yarn

| 执行 Linux 容器的组 |

对于 MapReduce(版本 1),

TaskController

类定义启动(和控制)哪个 Map 或 Reduce 任务,并使用一个名为

task-controller.cfg

的配置文件。该配置文件存在于 Hadoop 配置文件夹(

/etc/hadoop/conf/

)中,应该具有表 4-5 中列出的配置。

表 4-5 。

TaskController

配置

|

属性名称

|

属性值

|

描述

|
| — | — | — |
|

hadoop.log.dir

|

/var/log/hadoop-``0.20-mapreduce

| Hadoop 日志目录(将因您的 Hadoop 发行版而异)。该位置用于确保存在写入日志文件的适当权限。 |
|

mapreduce.``tasktracker.group

|

mapred

| 任务跟踪器所属的组 |
|

banned.users

|

mapred, hdfs,

bin

| 应该向其展示的用户运行 MapReduce |
|

min.user.id

|

1000

| 允许运行 MapReduce 任务的用户 ID |

这里有一个例子:

hadoop.log.dir=/var/log/hadoop-0.20-mapreduce/
mapred.local.dir=/opt/hadoop/hdfs/mapred/local
mapreduce.tasktracker.group=mapred
banned.users=mapred,hdfs,bin
min.user.id=500

请注意,

min.user.id

的值可能会因操作系统而异。一些操作系统使用 0 值而不是 500。

对于纱线,需要用表 4-6 中的配置定义

containerexecutor.cfg

表 4-6 。纱线

containerexecutor.cfg

配置

|

属性名称

|

属性值

|

描述

|
| — | — | — |
|

yarn.nodemanager.log-dirs

|

/var/log/yarn

| Hadoop 日志目录(将因您的 Hadoop 发行版而异)。该位置用于确保存在写入日志文件的适当权限。 |
|

yarn.nodemanager.linux-containerexecutor.group

|

yarn

| 容器所属的组 |
|

banned.users

|

hdfs, yarn, mapred,

bin

| 运行 mapreduce 时应该显示的用户 |
|

min.user.id

|

1000

| 允许运行 MapReduce 任务的用户 ID |

最后一步,您必须在文件

/etc/default/hadoop-hdfs-datanode

中的所有 DataNodes 上设置以下变量。这些变量为 Jsvc 提供了必要的信息,Jsvc 是一组使 Java 应用程序更容易在 Unix 上运行的库和应用程序,因此它可以在安全模式下运行 DataNode。

export HADOOP_SECURE_DN_USER=hdfs
export HADOOP_SECURE_DN_PID_DIR=/var/lib/hadoop-hdfs
export HADOOP_SECURE_DN_LOG_DIR=/var/log/hadoop-hdfs
export JSVC_HOME=/usr/lib/bigtop-utils/

如果目录

/usr/lib/bigtop-utils

不存在,将

JSVC_HOME

变量设置为

/usr/libexec/bigtop-utils

,如下所示:

export JSVC_HOME=/usr/libexec/bigtop-utils

因此,最后,在安装、配置和实现了 Kerberos 并修改了各种 Hadoop 配置文件(带有 Kerberos 实现信息)之后,您就可以启动带有认证的 NameNode 和 DataNode 服务了!

使用认证启动 Hadoop 服务

首先启动 NameNode。以

root

的身份执行以下命令,并替换正确的路径(Hadoop 启动脚本所在的位置):

su -l hdfs -c "export HADOOP_LIBEXEC_DIR=/usr/lib/hadoop/libexec && /usr/lib/hadoop/sbin/hadoop-daemon.sh --config /etc/hadoop/conf start namenode";

NameNode 启动后,您可以在 NameNode 日志文件中看到与 Kerberos 相关的消息,表明使用 keytab 文件成功进行了认证(对于主体

hdfs

http

):

信息安全。用户组信息(用户组信息. Java:loginUserFromKeytab(844))-用户 hdfs/pract_hdp_sec@EXAMPLE.COM 使用 Keytab 文件/etc/hadoop/conf/hdfs.keytab 成功登录

2013-12-10 14:47:24288 信息服务器。KerberosAuthenticationHandler(KerberosAuthenticationHandler . Java:init(185))-使用 keytab/etc/Hadoop/conf/HDFS . keytab 登录,用于主体 HTTP/pract_hdp_sec@EXAMPLE.COM

现在启动 DataNode:以

root

的身份执行以下命令,并替换正确的路径(Hadoop 启动脚本所在的位置):

su -l hdfs -c "export HADOOP_LIBEXEC_DIR=/usr/lib/hadoop/libexec && /usr/lib/hadoop/sbin/hadoop-daemon.sh --config /etc/hadoop/conf start datanode"

在 DataNode 启动后,您可以在 DataNode 日志文件中看到以下与 Kerberos 相关的消息,这些消息指示使用 keytab 文件成功进行了认证(针对主体

hdfs

)

信息安全。用户组信息(用户组信息. Java:loginUserFromKeytab(844))-用户 hdfs/pract_hdp_sec@EXAMPLE.COM 使用 Keytab 文件/etc/hadoop/conf/hdfs.keytab 成功登录

2013-12-08 10:34:34587 信息 http。http server(http server . Java:addGlobalFilter(525))-添加了全局过滤器’ safety '(class = org . Apache . Hadoop . http . http server $ QuotingInputFilter)

2013-12-08 10:34:35,502 信息数据节点。DataNode(blockpoolmanager . Java:doRefreshNamenodes(193))-为名称服务启动 BPOfferServices:

2013-12-08 10:34:35,554 信息数据节点。DataNode(bpserviceactor . Java:run(658))-块池(存储 id 未知)服务到 pract _ HDP _ sec/192 . 168 . 142 . 135:8020 开始提供服务

最后,启动 SecondaryNameNode。以

root

的身份执行以下命令,并替换正确的路径(Hadoop 启动脚本所在的位置):

su -l hdfs -c "export HADOOP_LIBEXEC_DIR=/usr/lib/hadoop/libexec && /usr/lib/hadoop/sbin/hadoop-daemon.sh --config /etc/hadoop/conf start secondarynamenode";

祝贺您,您已经成功地“kerberized 化”了 HDFS 服务!您现在也可以启动 MapReduce 服务了(您已经在 MapReduce 配置文件中设置了必要的主体和配置)。

请理解,我在本节中使用的命令可能会因操作系统(和 Hadoop 发行版)的版本而异。最好是查阅您的操作系统和 Hadoop 发行商的手册,以防出现任何错误或意外行为。

保护客户端-服务器通信

对于早期的 Hadoop 版本,当守护进程(或服务)相互通信时,它们不会验证另一个服务是否真的是它所声称的那样。因此,很容易启动一个流氓 TaskTracker 来访问数据块。模拟服务可以很容易地访问敏感数据、破坏数据或关闭集群!即使现在,除非您安装并配置了 Kerberos,并且加密了正确的通信协议,否则情况不会有很大的不同。对于 Hadoop 来说,保证进程间通信的安全是非常重要的。仅仅使用认证机制(比如 Kerberos)是不够的。您还必须保护 Hadoop 用于在其守护进程之间传输数据的所有通信方式,以及客户端和 Hadoop 集群之间的通信。

Hadoop 中的节点间通信使用 RPC、TCP/IP 和 HTTP 协议。具体来说,RPC(远程过程调用)用于 NameNode、JobTracker、DataNodes 和 Hadoop 客户端之间的通信。此外,客户端和 DataNodes 之间文件数据的实际读写使用 TCP/IP 协议,默认情况下该协议并不安全,这使得通信容易受到攻击。最后,HTTP 协议用于 web 控制台的通信,用于 NameNode/二级 NameNode 之间的通信,也用于 MapReduce shuffle 数据传输。除非受到保护,否则这种 HTTP 通信也容易受到攻击。

因此,您必须保护所有这些 Hadoop 通信,以便保护存储在 Hadoop 集群中的数据。你最好的选择是使用加密。恶意攻击者无法使用加密的数据,除非他们有解密的方法。您使用的加密方法取决于所涉及的协议。例如,为了加密 TCP/IP 通信,在 Hadoop 数据传输协议之上需要一个 SASL 包装器,以确保 Hadoop 客户端和 DataNode 之间的安全数据传输。Hadoop 的当前版本通过在配置文件

core-site.xml

hdfs-site.xml

中设置显式值来允许网络加密(结合 Kerberos)。为了保护使用 RPC 协议的 Hadoop 守护进程之间的进程间通信,您需要使用 SASL 框架。接下来的几节将进一步研究加密,从基于 RPC 的通信开始。

安全的进程间通信

Hadoop 中的进程间通信是通过 RPC 调用实现的。这包括 Hadoop 客户端和 HDFS 之间的通信,以及 Hadoop 服务之间的通信(例如,JobTracker 和 TaskTrackers 或 NameNode 和 DataNodes 之间的通信)。

SASL(简单认证和安全层)是认证框架,可用于保证客户端和服务器之间交换的数据被加密,并且不易受到“中间人”攻击(请参考第一章了解此类攻击的详细信息)。SASL 支持可用于不同上下文的多种认证机制(例如,MD5-DIGEST、GSSAPI、SASL 平原、CRAM-MD5)。

例如,如果您使用 Kerberos 进行认证,那么 SASL 会使用 GSSAPI(通用安全服务应用程序接口)机制来验证 Hadoop 客户端和 Hadoop 守护程序之间的任何通信。对于提交作业的安全 Hadoop 客户端(使用 Kerberos 进行认证),使用委托令牌认证,该认证基于 SASL MD5-DIGEST 协议。客户端向 NameNode 请求一个令牌,并将收到的令牌传递给 TaskTracker,并可以使用它与 NameNode 进行任何后续通信。

当您将 Hadoop 配置文件

core-site.xml

中的

hadoop.rpc.protection

属性设置为 privacy 时,RPC 上的数据将使用对称密钥加密。下面是 XML:

<property><name>hadoop.rpc.protection</name><value>privacy</value><description>authentication, integrity & confidentiality guarantees that data exchanged between client and server is encrypted
</description></property>

然而,加密是有代价的。如表 4-1 所述,将

hadoop.rpc.protection

设置为

privacy

意味着 Hadoop 执行完整性检查、加密和认证,所有这些额外的处理都会降低性能。

加密 HTTP 通信

Hadoop 将 HTTP 通信用于 web 控制台、NameNode/二级 NameNode 之间的通信以及 MapReduce(混洗数据)。对于 MapReduce 作业,数据通过 HTTP 协议在映射器和 Reducers 之间移动,这个过程称为 shuffle 。缩减器启动到映射器的连接,请求数据,并充当 SSL 客户端。下面将详细介绍启用 HTTPS 加密无序传输流量的步骤。

证书用于保护使用 HTTP 协议的通信。您可以使用 Java 实用工具 keytool 来创建和存储证书。证书存储在密钥库(文件)中,包含密钥(私钥和身份)或证书 (公钥和身份)。有关密钥库的其他详细信息,请参考第八章和附录 c。一个信任库文件包含来自可信来源的证书,由安全 HTTP (https)客户端使用。Hadoop HttpServer 使用密钥库文件。

创建 HTTPS 证书并将其分发到所有节点后,您可以为 HTTP 加密配置 Hadoop。具体来说,您需要通过在 Hadoop 配置文件

hdfs-site.xml

中将属性

dfs.https.enable

设置为

true

来在 NameNode 和所有 DataNodes 上配置 SSL。

大多数时候,SSL 被配置为只对服务器进行认证,这种模式被称为单向 SSL 。对于单向 SSL,您只需要在 NameNode(和每个 DataNode)上配置 KeyStore,使用表 4-7 中的所示的属性。这些参数在 NameNode 和每个 DataNodes 上的

ssl-server.xml

文件中设置。

您还可以配置 SSL 来验证客户端;这种模式被称为相互认证双向 SSL 。要配置双向 SSL,除了将属性

dfs.https.enable

设置为

true

之外,还要在 Hadoop 配置文件

hdfs-site.xml

中将属性

dfs.client.https.need-auth

设置为

true

(在 NameNode 和每个 DataNode 上)。

表 4-7 。加密 HTTP 通信的 SSL 属性

|

财产

|

缺省值

|

描述

|
| — | — | — |
|

ssl.server.keystore.type

|

jks

| 密钥库文件类型 |
|

ssl.server.keystore.location

|

NONE

| 密钥库文件位置。

mapred

用户应该拥有这个文件,并拥有对它的独占读取权限。 |
|

ssl.server.keystore.password

|

NONE

| 密钥库文件密码 |
|

ssl.server.truststore.type

|

jks

| 信任库文件类型 |
|

ssl.server.truststore.location

|

NONE

| 信任库文件位置。

mapred

用户必须是具有独占读取权限的文件所有者。 |
|

ssl.server.truststore.password

|

NONE

| 信任库文件密码 |
|

ssl.server.truststore.reload.interval

|

10000

| 信任库重新加载间隔,以毫秒为单位 |

附录 C 详细介绍了如何设置用于 HTTP 加密的密钥库和信任库。

要配置加密混洗,需要在集群中所有节点的

core-site.xml

文件中设置表 4-8 中列出的属性。

表 4-8 。

core-site.xml

启用加密随机播放的属性(适用于 MapReduce)

|

财产

|

价值

|

说明

|
| — | — | — |
|

hadoop.ssl.enabled

|

true

| 对于 MRv1,将该值设置为

true

将启用加密随机播放和加密 Web UI 功能。对于 MRv2,该属性只启用加密的 WebUI 如“加密 HTTP 通信”中所述,使用

mapred-site.xml

文件中的一个属性启用加密无序播放 |
|

hadoop.ssl.require. client.cert

|

true

| 当设置为

true

时,所有随机播放操作和用于访问 Web 用户界面的所有浏览器都需要客户端证书。 |
|

hadoop.ssl.hostname. verifier

|

DEFAULT

| 为

HttpsURLConnections

提供的主机名验证器。有效值为

DEFAULT

STRICT

STRICT_I6

DEFAULT_AND_LOCALHOST

ALLOW_ALL

。 |
|

hadoop.ssl.keystores. factory.class

|

org.apache.hadoop.security. ssl.FileBasedKeyStoresFactory

| 要使用的

KeyStoresFactory

实现。 |
|

hadoop.ssl.server.conf

|

ssl-server.xml

| 从中提取 SSL 服务器密钥库信息的资源文件。在类路径中查找该文件;通常它应该在

/etc/hadoop/conf/

目录中。 |
|

hadoop.ssl.client.conf

|

ssl-client.xml

| 从中提取 SSL 服务器密钥库信息的资源文件。在类路径中查找该文件;通常它应该在

/etc/hadoop/conf/

目录中。 |

要为 MRv2 启用加密混洗,请在集群中的每个节点上将

mapred-site.xml

文件中的属性

mapreduce.shuffle.ssl.enabled

设置为

true

总而言之,要配置加密随机播放(针对 MapReduce 作业)和加密 Web 用户界面,需要使用/修改以下配置文件:

  • core-site.xml / hdfs-site.xml:启用 HTTP 加密,定义实现
  • mapred-site.xml:启用 MRv2 的加密洗牌
  • ssl-server.xml:存储服务器的密钥库和信任库设置
  • ssl-client.xml:存储客户端的密钥库和信任库设置

保护数据通信

客户端和 DataNodes 之间的数据传输(读/写)使用 Hadoop 数据传输协议。因为这里没有使用 SASL 框架进行认证,所以如果数据传输需要安全或加密,则需要 SASL 握手包装器。这个包装器可以通过在配置文件

hdfs-site.xml

中将属性 dfs.encrypt.data.transfer 设置为 true 来启用。当启用 SASL 包装器时,NameNode 会生成一个数据加密密钥,并将其传递给 DataNodes 和客户端。客户端使用该密钥作为任何后续通信的凭证。NameNode 和 DataNodes 使用它来验证客户端通信。

如果您对想要用于加密的实际算法有偏好,可以使用属性

dfs.encrypt.data.transfer.algorithm

来指定。可能的值是

3des

rc4

(默认值通常是 3DES。)3DES 或“三重 DES”是流行的对称密钥算法 DES 的变体,它使用三个密钥(而不是 DES 使用的单个密钥)来增强协议。你用一个密钥加密,用第二个解密,用第三个加密。该过程给出了相当于 112 位密钥(而不是 DES 的 56 位密钥)的强度,并使加密更强,但速度较慢(由于加密需要多次迭代)。有关 DES 协议的更多详细信息,请参考第八章中的。RC4 是另一种对称密钥算法,与 3DES 相比,它执行加密的速度快得多,但具有潜在的不安全性(微软和思科都在逐步淘汰这种算法,并向用户提供了避免使用它的明确指南)。

请注意,由于 RPC 协议用于向客户端发送数据加密密钥,因此有必要在配置文件

core-site.xml

中将

hadoop.rpc.protection

设置配置为

privacy

(客户端和服务器都适用),以确保密钥本身的传输是加密和安全的。

摘要

在本章中,您学习了如何从客户端开始,为您的 Hadoop 集群建立整体安全性或“防护”。目前,PuTTY 为保护您的客户端提供了最好的开源选项。我讨论了使用密钥对和密码短语,而不是我们熟悉的登录/密码。原因很简单——让恶意攻击更难突破您的安全。每个人都使用过 PuTTY,但是很多时候他们没有考虑底层技术和使用一些可用选项的原因。我曾试图阐明腻子的这些方面。

我不确定麻省理工学院开发 Kerberos 时是否考虑了 Hadoop 但是目前 Kerberos 和 Hadoop 的使用可能会让你有不同的想法!同样,这是(到目前为止)Hadoop 认证最流行的替代方案。

对于非 Java 人员来说,处理密钥库和信任库总是有点困难。如果你需要另一个例子,附录 C 将帮助你进一步理解这些概念。

使用 SASL 协议进行 RPC 加密和加密数据传输协议的底层技术是复杂的主题。本章中实现安全集群的例子仅仅是为了介绍这个主题。

你从这里去哪里?既然您的群集外围已经安全,那么这项工作是否已经完成?肯定不是!这就是它开始的地方——它通过指定更详细的授权来进一步保护您的集群。那是下一章的主题。

五、实现粒度授权

设计细粒度的授权让我想起了一个故事,一位著名的银行经理被一次对他的保险箱的抢劫所困扰。银行经理非常不安,他立即为金库设置了多层安全和密码。第二天,客户要求他打开保险库。经理在极度兴奋中忘记了密码,保险库不得不被强行打开(当然是合法的)。

您可能会发现,设计细粒度的安全性是一个棘手的问题。太多的安全和太少的安全一样会适得其反。没有什么魔法可以让它变得恰到好处。如果您分析了所有流程(包括手动和自动流程)并对数据进行了很好的分类,您就可以确定谁需要访问哪些特定资源以及需要什么级别的访问权限。这就是细粒度授权的定义:每个用户都拥有对必要资源的正确访问级别。微调 Hadoop 安全性以允许由功能需求驱动的访问将使您的 Hadoop 集群更不容易受到黑客和未授权访问的攻击,而不会牺牲可用性。

在本章中,您将学习如何确定安全需求(基于应用程序),然后研究如何使用目录和文件级权限为应用程序设计高级安全性和细粒度授权。为了说明这一点,我将带您看一个修改过的真实世界的例子,这个例子涉及交通罚单数据以及警察、法院和报告机构对这些数据的访问。本章最后讨论了如何使用 Apache Sentry 实现细粒度的授权,并回顾了交通票据的例子,以突出 Sentry 在 Hive 中的使用,Hive 是一个与 HDFS 协同工作的数据库。在本章结束时,你将会对如何设计细粒度授权有一个很好的理解。

设计用户授权

定义细粒度授权的细节是一个多步骤的过程。这些步骤是:

  1. 分析你的环境,
  2. 对数据进行分类以便访问,
  3. 确定谁需要访问什么数据,
  4. 确定必要的访问级别,以及
  5. 实现您设计的安全模型。

下面几节将通过这个完整的过程来定义真实场景中的细粒度授权。

打电话给警察:一个真实世界的安全例子

几年前我为芝加哥警察局做过一些工作,涉及到该部门的票务系统。该系统基本上有三个部分:警车上的移动控制台,当地警察局的本地数据库,以及芝加哥市中心警察总部的中央数据库。为什么微调授权在这种情况下很重要?考虑一下没有它的潜在滥用:例如,如果 it 部门拥有对数据的修改权限,某个既得利益者可以修改特定票据的数据。最初的系统是使用 Microsoft SQL Server 开发的,但是对于我的例子,我将针对 Hadoop 环境重新设计它。同时,您还将了解 Hadoop 实现与基于关系数据库的实现有何不同。

分析和分类数据

第一步是检查和分析所涉及的系统(或应用程序)。此外,审查系统的高级目标和用例有助于阐明访问需求。在考虑用例时,不要忘记维护、备份和灾难恢复。系统概述是一个很好的起点,回顾所涉及的手动过程也是如此(按照逻辑顺序)。在这两种情况下,您的目标是了解每个流程中的功能需求,了解流程之间的交互方式,确定每个流程中生成的数据,并跟踪这些数据是如何传递给下一个流程的。图 5-1 说明了一个系统的分析。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-1 。分析系统或应用程序

在我的例子中,第一个过程是由警官(签发罚单的人)生成罚单数据。这些数据被传输到当地警察局的数据库中,显然,检票员、他或她在警察局的主管以及警察总部的上层管理人员都需要拥有修改权限。

当地警察局的其他警察需要读取这些数据的权限,因为他们可能想要查看在特定日期开出的所有罚单或一个人的驾驶历史,同时决定是开罚单还是只开警告。因此,警官在当地警察局数据库(当天)以及位于警察总部的中央数据库中查找罚单数据(使用司机的社会安全号码或 SSN)。

作为第二个过程,来自当地警察局(来自整个芝加哥地区)的罚单数据每晚被传送到警察总部的中央数据库。

第三个也是最后一个过程是每天晚上为所有警察局的主管自动生成每日报告。这些报告汇总了当天的票证活动,由报告用户(由 IT 创建)运行。

票证数据的详细信息

这个票据数据不是一个单独的实体,而是一组包含所有数据的相关实体。理解保存这些数据的数据库的设计将有助于设计详细的安全级别。

两个,或者 Hadoop 术语中的文件,保存所有的票数据。正如表被用来在关系数据库中存储数据一样,HDFS 使用文件。在这种情况下,假设 Hadoop 将数据存储为逗号分隔的文本文件。(当然,Hadoop 支持多种格式来存储数据,但是一个简单的例子有助于更好地理解这些概念。)表格和文件详情汇总在图 5-2 中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-2 。票证数据的详细信息:信息的分类和表格与文件的存储

第一个表

Driver_details

,保存司机的所有个人信息:合法全名、SSN、当前地址、电话号码等等。第二个表

Ticket_details

包含罚单的详细信息:罚单编号、司机的 SSN、违规代码、签发官员等等。

此外,这些表彼此“相关”。关系符号表明每个司机(在

Driver_details

中出现)可能有一张或多张他名下的票,细节在

Ticket_details

中。罚单怎么会和司机有关系?通过使用 SSN。SSN 是主键(表示为 PK )或

Driver_details

表的唯一标识符,因为 SSN 唯一地标识一个驱动程序。然而,由于一个司机可能有多张票,SSN 不是

Ticket_details

表的唯一标识符,仅用于将票关联到一个司机(表示为 FK外键)。

请理解,票证数据示例非常简单,只是演示了如何使用粒度权限。此外,它还做出了以下假设:

  • 该示例使用 Hadoop 2.x,因为我们需要向所有数据文件追加数据,而早期版本不支持追加。当地警察局当天的所有罚单将在每晚附加到位于警察总部的适当数据文件中。
  • 记录不会被更新,但状态标志将用于指示活动记录(最近的记录被标记为活动的,较早的记录被标记为非活动的)。
  • 没有对记录的并发修改。
  • 在写入数据时没有会损害系统完整性的故障。
  • 功能需求是,只有警官(签发罚单的人)、警官的主管和更高级别的管理人员应该有权修改罚单,但是这种期望的粒度在 HDFS 中是不可能的!为此需要使用 Hive 或另一个 NoSQL 数据库。目前,我只是给所有警察提供了修改权。然而,在下一节中,您将学习如何使用 Hive 和 Sentry 来重新实现这个示例,以达到期望的粒度。

生产系统可能要复杂得多,需要更复杂的设计来保证有效的安全性。

回到我们的例子,我们如何设计角色来保护票据数据并根据需要提供访问?我们的设计必须满足所有的功能需求(对于系统内的所有过程),而不提供太多的访问(由于数据的敏感性)。本节的下一部分将解释如何实现。

确定访问组及其访问级别

根据三个流程的功能需求,车票数据需要读写(修改)访问权限。接下来的问题是,哪些组需要哪些权限(图 5-3 )?三个子组需要对此数据的部分读写权限;称他们为第一组:

  • 出票警官
  • 当地警察主管
  • 总部的高级管理层

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-3 。使用详细的访问权限对票证数据进行分组访问

第 2 组,警察总部的 IT 部门,需要读取权限。图 5-3 说明了这种访问。

表 5-1 列出了权限。

表 5-1 。组和实体的权限详细信息(表)
|

桌子

|

第一组

|

第二组

|
| — | — | — |
|

Driver_details

| 读/写 | 阅读 |
|

Ticket_details

| 读/写 | 阅读 |

因此,总结、分析和分类您的数据,然后确定需要访问数据适当部分的逻辑组。有了这些认识,您就可以设计用于定义细粒度授权的角色,并确定这些角色所需的权限组。

逻辑设计(即使是像票务系统这样非常高级的例子)也必须导致物理实现。只有这样,你才能有一个有效的系统。下一节重点介绍实现该示例设计的细节。

实现安全模型

实现安全模型是一个多步骤的过程。一旦您很好地理解了角色及其权限需求,您就可以开始了。以下是要遵循的步骤:

  1. 安全的数据存储。
  2. 根据需要创建用户和组。
  3. 分配所有权、组和权限。

理解一些关于 Hadoop 文件权限的基本事实将在这个过程中帮助你。

Hadoop 中的票证数据存储

对于票务系统的例子,我将从在 HDFS 实现数据存储开始。正如您之前看到的,Hadoop 中的数据存储在文件

Driver_details

Ticket_details

中。这些文件位于 Hadoop 的根数据目录下,如图图 5-4 所示。为了更好地理解该图,考虑一些关于 HDFS 文件权限的基本事实。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-4 。HDFS 目录和文件权限

  • HDFS 文件有三组权限,分别针对所有者、组和其他人。使用十个字符的字符串来指定权限,比如-rwxrwxrwx
  • 第一个字符表示目录或文件(-表示文件或d表示目录),接下来的三个字符表示文件所有者的权限,接下来的三个表示所有者的组,最后三个表示其他组。
  • 任何分组的可能值是r(读权限)、w(写权限)、x(执行权限)或(占位符)。注意x只对可执行文件或目录有效。

在图 5-4 中,文件

Driver_details

ticket_details

的所有者(root)拥有

rw-

权限,即读写权限。接下来的三个字符是组的权限(意味着属于该文件所属组的所有用户,在本例中为

hdfs

)。组的权限为

rw-

,表示所有组成员对该文件都有读写权限。最后三个字符表示对其他人的权限(不拥有该文件且不属于该文件所属的同一组的用户)。对于这个例子,其他人只有读权限(

r--

)。

添加 Hadoop 用户和组以实现文件权限

作为实现该系统基本授权的最后一步,我需要在 Hadoop 中定义适当的用户和组,并调整文件权限。

首先,我为这个服务器创建了与示例中的两个组相对应的组:组 1 称为

POfficers

,组 2 称为

ITD

[root@sandbox~]# groupadd POfficers
[root@sandbox~]# groupadd ITD

列出并验证组是一个好主意:

[root@sandbox~]# cut –d:-f1 /etc/group | grep POfficers

我还为组

POfficers

创建了用户

Puser

,为组

ITD

创建了用户

Iuser

:

[root]# useradd Puser –gPOfficers
[root]# useradd Iuser –gITD

接下来,我设置了密码:

[root]# passwd Puser
Changing password for user Puser.
New password:
Retype password:
Passwd: all authentication tokens updated successfully.

现在,作为最后一步,我分配所有者和组来实现权限。在图 5-5 中可以看到,文件

Driver_details

Ticket_details

的所有者被更改为虚拟用户

Puser

,组权限被设置为写;因此来自组

POfficers

(所有警察)的用户将拥有读/写权限,来自其他组的用户(即 IT 部门)将只有读取权限。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-5 。更改 HDFS 文件的所有者和组

将表 5-1 与所有实体(HDFS 同名文件)的最终权限进行比较,你会发现目标已经达到:

Puser

拥有文件

Driver_details

Ticket_details

,属于组

POfficers

(组 1)。权限

-rw-rw-r--

表示组 1 中的任何一个用户都有读/写权限,而属于任何其他组(例如组 2)的用户只有读权限。

这个例子让您对 Hadoop 集群的微调授权有了一个基本的了解。不幸的是,现实世界是复杂的,我们不得不与之打交道的系统也是如此!所以,为了让事情更真实一点,我将扩展这个例子,你可以看到在票旁边发生了什么。

扩展票证数据

罚单只来自警方。最终,法院会介入进一步处理罚单。因此,一些票据数据需要与司法系统共享。该组需要读取以及修改数据的某些部分的权利,但只有在罚单通过交通法院处理后。此外,机票数据的某些部分需要与报告机构共享,报告机构根据需要将这些数据提供给保险公司、征信机构和其他国家实体。

这些假设不会改变基本组,但将需要两个新的组:一个用于司法机构(组 3),另一个用于报告机构(组 4)。现在权限结构看起来像图 5-6 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-6 。使用详细的访问权限对票证数据进行分组访问,显示新的组

随着功能和组的增加,数据也必须增加。例如,表

Judgement_details

将包含罚单的司法历史,比如案件日期、最终判决、罚单支付细节等等。Hadoop 将以相同的名称将该表存储在一个文件中(图 5-7 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-7 。票证数据的详细信息—信息分类—增加了法律详细信息表

像图 5-2 ,图 5-7 也说明了如果关系数据库用于存储,数据将如何保存在表格中。这只是为了比较 Hadoop 中的数据存储和关系数据库系统中的数据存储。正如我前面所讨论的,存储在关系数据库系统中的数据是相关的:司机数据(

Driver_details

表)与票据数据(

Ticket_details

表)相关,使用 SSN 来关联或链接数据。使用附加表(

Judgement_details

),票据的法院判决再次使用 SSN 与驾驶员和票据细节相关或链接。

众所周知,Hadoop 使用文件来存储数据。所以,就 Hadoop 而言,有一个额外的数据文件用于存储与司法相关的数据—

Judgement_details

。没有关联或链接存储在多个文件中的数据的概念。当然,您可以通过编程的方式链接数据,但是 Hadoop 不会自动为您这样做。当您在 HDFS 存储数据时,了解这种差异非常重要。

添加一个表也会改变权限结构,正如你在表 5-2 中看到的。

表 5-2 。组和实体的权限详细信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加新的组增加了可能的权限排列,但无助于解决复杂的权限需求(请参考“使用 Apache Sentry 进行基于角色的授权”一节,以了解如何实现粒度权限)。例如,如果警察部门只希望出票官员和车站负责人拥有车票的书面许可,该怎么办?在图 5-7 和表 5-2 中定义的组显然不能用于实现这一要求。针对如此复杂的需求,Hadoop 提供了访问控制列表(ACL),与 Unix 和 Linux 使用的 ACL 非常相似。

HDFS 的访问控制列表

根据 HDFS 权限模型,对于任何文件访问请求,HDFS 会针对最适用的特定用户类别实现权限。例如,如果请求者是文件所有者,则检查所有者类权限。如果请求者是拥有该文件的组的成员,则检查组类权限。如果请求者不是文件所有者或文件所有者组的成员,则检查其他类权限。

这种权限模型适用于大多数情况,但不是所有情况。例如,如果所有警察、IT 部门经理和负责管理票务系统的系统分析师都需要对

Ticket_details

Driver_details

文件的写权限,那么现有的四个组不足以实现这些安全要求。您可以创建一个名为

Ticket_modifiers

的新所有者群组,但是保持群组成员的最新状态可能会有问题,因为人员变动(人们更换工作),以及由手动错误或疏忽导致的错误或不适当的权限。

用于限制对数据的访问,ACL 在您的权限需求复杂且具体的情况下提供了一个非常好的替代方案。因为 HDFS 使用与 Linux 相同的(基于 POSIX 的)权限模型,所以 HDFS ACL 是模仿 Unix 和 Linux 已经使用了很长时间的 POSIX ACLs。Apache Hadoop 2.4.0 以及所有其他主要供应商的发行版中都提供了 ACL。

除了文件的所有者和组之外,您还可以使用 HDFS ACL 为特定用户或组定义文件权限。但是,对文件使用 ACL 确实会导致 NameNode 使用额外的内存,因此您的最佳实践是为特殊情况保留 ACL,并为常规安全实现使用个人和组所有权。

要使用 ACL,您必须首先在 NameNode 上启用它们,方法是将以下配置属性添加到

hdfs-site.xml

并重新启动 NameNode:

<property><name>dfs.namenode.acls.enabled</name><value>true</value></property>

启用 ACL 后,HDFS CLI(命令行界面)中会添加两个新命令:

setfacl

getfacl

setfacl

命令分配权限。通过它,我可以为票务示例的 it 经理(

ITMgr

)和分析师(

ITAnalyst

)设置读写权限:

> sudo -u hdfs hdfs dfs -setfacl -m user:ITMgr:rw-/Driver_details
> sudo -u hdfs hdfs dfs -setfacl -m user:ITAnalyst:rw-/Driver_details

使用

getfacl

,我可以验证权限:

> hdfs dfs -getfacl /Driver_details
# file:/Driver_details
# owner: Puser
# group: POfficers
user::rw-
user:ITAnalyst:rw-
user:ITMgr:rw-
group::r--
mask::rw-
other::r--

当 ACL 被启用时,文件列表显示

a + in

权限:

> hdfs dfs -ls /Driver_details
-rw-rw-r--+1 Puser POfficers 192014-09-1918:42/Driver_details

您可能会遇到需要对目录中的所有文件或目录中的所有子目录和文件应用特定权限的情况。在这种情况下,您可以为目录指定默认 ACL,该 ACL 将自动应用于该目录中所有新建的子文件和子目录:

> sudo -u hdfs hdfs dfs -setfacl -m default:group:POfficers:rwx /user

验证权限显示已应用默认设置:

> hdfs dfs -getfacl /user

# file:/user
# owner: hdfs
# group: hdfs
user::rwx
group::r-x
other::r-x
default:user::rwx
default:group::r-x
default:group:POfficers:rwx
default:mask::rwx
default:other::r-x

请注意,在我们的简单示例中,我为来自组

POfficers

的所有用户保留了

rw-

访问权限,因此 ACL 实际上没有限制任何内容。在现实世界的应用程序中,我很可能会将组

POfficers

的访问权限限制为比批准的 ACL 定义的用户更少(可能只是读权限)。

请注意

hdfs

将默认 ACL 仅应用于新创建的子目录或文件;默认 ACL 的应用或对父目录的默认 ACL 的后续更改不会自动应用到现有子目录或文件的 ACL。

您还可以使用 ACL 来阻止特定用户对目录或文件的访问,而不会意外撤销任何其他用户的权限。假设一名分析师已被调到另一个部门,因此不再有权访问票据信息:

> sudo -u hdfs hdfs dfs -setfacl -m user:ITAnalyst:---/Driver_details

验证更改:

> hdfs dfs -getfacl /Driver_details

# file:/Driver_details
# owner: Puser
# group: POfficers
user::rw-
user:ITAnalyst:---
user:ITMgr:rw-
group::r--
mask::rw-
other::r--

有效使用 ACL 的关键是了解用户访问 HDFS 文件时 ACL 条目的评估顺序。权限按以下顺序评估和实现:

  1. 如果用户拥有该文件,则强制实现所有者权限。
  2. 如果用户有 ACL 条目,则这些权限将被强制执行。
  3. 如果用户是(文件所有权)组的成员,则使用这些权限。
  4. 如果某个组有一个 ACL 条目,并且用户是该组的成员,则使用这些权限。
  5. 如果用户是文件组或任何其他具有拒绝访问文件的 ACL 条目的组的成员,则用户被拒绝访问(文件)。如果用户是多个组的成员,则对所有匹配条目实现权限联合。
  6. 最后,如果没有其他权限适用,则使用组others的权限。

总而言之,HDFS ACL 对于实现复杂的权限需求或向特定用户或组提供不同于文件所有权的权限非常有用。但是,请记住,要明智地使用 ACL,因为带有 ACL 的文件会导致 NameNode 占用更多的内存。如果您确实计划使用 ACL,请确保在确定 NameNode 内存大小时考虑到这一点。

基于角色的 Apache Sentry 授权

Sentry 是一个为存储在 HDFS 的数据提供基于角色的授权的应用程序,由 Cloudera 开发并提交给 Apache Hadoop 社区。它提供了与关系数据库非常相似的细粒度授权。在撰写本文时,Sentry 是为存储在 HDFS 的数据提供 RBAC(基于角色的授权控制)的最成熟的开源产品,尽管 Hortonworks (Argus)的另一个项目是一个挑战者。Sentry 目前与 Hive(由 Apache 软件基金会提供的数据库/数据仓库)和 Impala(由 Cloudera 开发的查询引擎,受谷歌 Dremel 的启发)合作。

Hive 架构和授权问题

Hive 是一个与 HDFS 合作的数据库。它的查询语言在语法上非常类似于 SQL,这也是它受欢迎的原因之一。需要记住的数据库的主要方面如下:

  • Hive 将数据组织成熟悉的数据库概念,如表、行、列和分区。
  • Hive 支持原始数据类型:整数、浮点数、双精度数和字符串。
  • 配置单元表是 HDFS 目录(和其中的文件)。
  • 分区(对于配置单元表)是“表”HDFS 目录中的子目录。
  • 配置单元权限存在于数据库或表级别,可以授予用户、组或角色。
  • 配置单元权限包括 select(读取)、update(修改数据)和 alter(修改元数据)。

然而,Hive 并不完美。它使用存储库(Metastore)来存储与表相关的元数据,因此,如果直接更改底层 HDFS 对象的权限,可能会出现表元数据和 HDFS 权限不匹配的情况。Hive 没有能力阻止或识别这种情况。因此,通过用户的操作系统用户或组,用户可能被授予对某个表的 select 权限,但对 HDFS 内的相应目录/文件具有 update 或 write 权限。此外,Hive 无法为表数据的特定部分或部分表数据提供权限。无法提供列级权限、定义视图(用于更精细的数据访问控制)或定义服务器级角色。

Sentry 解决了其中的一些问题。它提供了服务器、数据库和表级别的角色,并且可以使用 Hive 外部表—您可以使用这些表对用户进行部分数据访问控制。

图 5-8 展示了 Hive 的架构以及它与 HDFS 的关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-8 。Hive 体系结构及其授权

哨兵建筑

作为一个集成了 Hive 和 Impala 的安全模块,Sentry 提供了高级授权控制,能够更安全地访问 HDFS 数据。我们将关注 Sentry 与 Hive 的集成(因为它的使用更广泛)。Sentry 使用规则为数据库对象指定精确的权限,并使用角色来组合或合并规则,从而可以轻松地对不同数据库对象的权限进行分组,同时提供为各种类型的权限创建规则的灵活性(如选择或插入)。

为哨兵创建规则和角色

Sentry 使用规则授予精确的控制权,以指定用户对数据库、模式或表中数据子集的访问。例如,如果数据库

db1

有一个名为

Employee

的表,那么为

Insert

提供访问的规则可以是:

server=MyServer->db=db1->table=Employee->action=Insert

一个角色是一组访问配置单元对象的规则。各个规则用逗号分隔,并分组形成一个角色。

例如,

Employee_Maint

角色可以指定为:

Employee_Maint = server=Myserver->db=db1->table=Employee->action=Insert, \
server=server1->db=db1->table=Employee_Dept->action=Insert, \
server=server1->db=db1->table=Employee_salary->action=Insert

这里,

Employee_Maint

角色允许任何用户(拥有该角色)在表

Employee

Employee_Dept

Employee_salary

中插入行。

基于角色的授权简化了权限管理,因为管理员可以根据其组织内的职能角色为权限分组创建模板。

多部门管理使中央管理员能够委托单个管理员使用数据库级角色管理每个独立数据库或模式的安全设置。例如,在下面的代码中,

DB2_Admin

角色授权数据库

db2

的所有权限,而

Svr_Admin

授权服务器

MyServer

的所有权限:

DB2_Admin = server=MyServer->db=db2
Svr_Admin = server=MyServer

在 Sentry 中创建规则和角色只是第一步。如果要使用角色,需要将角色分配给用户和组。Sentry 如何识别用户和群组?下一节将对此进行解释。

了解 Sentry 中的用户和组

用户是由认证子系统认证并被允许访问 Hive 服务的人。因为该示例假设正在使用 Kerberos,所以用户将是 Kerberos 主体。一个是被授予一个或多个授权角色的一个或多个用户的集合。Sentry 目前支持 HDFS 支持的组和本地配置的组(在配置文件

policy.xml

中)。例如,考虑

policy.xml

中的以下条目:

Supervisor = Employee_Maint, DB2_Admin

如果

Supervisor

是一个 HDFS 支持的组,那么属于这个组的所有用户都可以执行角色

Employee_Maint

DB2_Admin

允许的任何 HiveQL 语句。但是,如果

Supervisor

是一个本地组,那么属于这个组的用户(称他们为

ARoberts

MHolding

)必须在文件

policy.xml

中定义:

[users]
ARoberts = Supervisor
MHolding = Supervisor

图 5-9 展示了 Sentry 在带有 Kerberos 认证的 Hadoop 架构中的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-9 。使用 Sentry 的 Hadoop 授权

总的来说,在回顾了 Hive 和 Sentry 架构之后,您已经了解了它们各自提供的安全范围。您已经简要了解了如何设置规则、角色、用户和组。因此,您现在已经准备好重新实现本章前面部分定义的票务系统(使用 Sentry)。

实现角色

在用适当的规则、角色、用户和组重新实现票务系统之前,花点时间回顾一下它的功能需求。罚单是由开罚单的警察开出的。罚单数据存储在当地警察局的数据库中,所有警察都需要有修改权限。位于警察总部的 IT 部门需要对这些数据的读取权限,以便进行报告。一些罚单数据由司法系统共享,他们需要对部分数据的读取和修改权限,因为数据在罚单通过交通法院处理后被修改。最后,这些数据的某些部分需要与报告机构共享,这些报告机构根据需要向保险公司、征信机构和其他国家机构提供这些数据。表 5-3 总结了这些要求;更多细节,请参考图 5-7 。

表 5-3 。组和实体的权限详细信息

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最初使用 HDFS 文件权限的实现很简单,但是没有考虑以下问题:

  • 创建票证时,会自动创建一个司法记录(案例),其中包含父记录ticket_id(指明该案例属于哪个票证)和案例详细信息。警察应该有权将该记录插入到包含罚单详细信息的Judgement_details表中,但不允许修改判决和其他案件详细信息的列。文件权限不够灵活,无法实现这一要求。
  • (为案例分配的)法官应该对包含案例详细信息的列拥有修改权限,但不应该对包含票证详细信息的列拥有修改权限。还是那句话,文件权限处理不了这个。

要实现这些需求,您需要 Sentry(或其等价物)。然后,使用 Hive,您需要创建具有相关列的外部表(司法人员或警察需要写访问的列),并为适当的部门提供对这些外部表的写访问,而不是对

Ticket_details

Judgement_details

表的写访问。

对于此示例,假设集群(用于实现)运行的是 CDH4.3.0 (Cloudera Hadoop 发行版 4.3.0)或更高版本,并且安装了带有 Kerberos 认证的 HiveServer2。

作为第一步,您需要进行一些配置更改。将配置单元仓库目录(

/user/hive/warehouse

或配置单元配置文件

hive-site.xml

中为属性

hive.metastore.warehouse.dir

指定的任何其他路径)的所有权更改为用户

hive

和组

hive

。将仓库目录的权限设置为

770 (rwxrwx---)

,即所有者和组的读、写、执行权限;但是对于

others

或不属于组

hive

的用户没有权限。您可以在

hive-site.xml

中将属性

hive.warehouse.subdir.inherit.perms

设置为

true

,以确保子目录上的权限也将被设置为

770

。接下来,将属性

hive.server2.enable.doAs

更改为

false

。这将作为运行服务

Hiveserver2

的用户执行所有查询。最后,在配置文件

taskcontroller.cfg

中将属性

min.user.id

设置为

0

。这是为了确保

hive

用户可以提交 MapReduce 作业。

完成这些配置更改后,您就可以设计必要的表、规则、角色、用户和组了。

设计表格

您需要创建表

Driver_details

Ticket_details

Judgement_details

,以及一个外部表

Judgement_details_PO

,如下所示:

CREATE TABLE Driver_details (SocialSecNum STRING,
Last Name STRING,
First Name STRING,
Address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>,
Phone BIGINT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/Driver_details";

CREATE TABLE Ticket_details (TicketId BIGINT,
DriverSSN STRING,
Offense STRING,
Issuing Officer STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/Ticket_details";

CREATE TABLE Judgement_details (CaseID BIGINT,
TicketId BIGINT,
DriverSSN STRING,
CaseDate STRING,
Judge STRING,
Judgement STRING,
TPaymentDetails STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/Judgement_details";

CREATE EXTERNAL TABLE Judgement_details_PO (CaseID BIGINT,
TicketId BIGINT,
DriverSSN STRING)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\;'
LOCATION "/user/hive/warehouse/Judgement_details";

如果你参考图 5-5 中的,你会发现我使用了相同的列(就像我们在 Hadoop 文件或表格中使用的一样)来创建这些表格,并且只是根据需要替换数据类型(例如,

Last Name

是一个字符串,或者数据类型

STRING

;但是

TicketId

是大整数还是

BIGINT

。最后一个表

Judgement_details_PO

被创建为 Hive 外部表,这意味着 Hive 只管理这个表的元数据,而不管理实际的数据文件。我创建这个表作为外部表,表的前两列是

Judgement_details

,因为我需要某些资源来拥有只修改这两列的权限——而不是那个表中的其他列。

设计规则

我需要设计规则来提供实现票务系统所需的安全性。该示例有四个表,各种角色将需要读取(选择)或修改(插入)权限,因为没有对 Hive 或 HDFS 数据的“更新”。我将简单地追加(或插入)记录的新版本。所以,规则如下:

server=MyServer->db=db1->table=Driver_details->action=Insert
server=MyServer->db=db1->table=Ticket_details->action=Insert
server=MyServer->db=db1->table=Judgement_details->action=Insert
server=MyServer->db=db1->table=Judgement_details_PO->action=Insert
server=MyServer->db=db1->table=Driver_details->action=Select
server=MyServer->db=db1->table=Ticket_details->action=Select
server=MyServer->db=db1->table=Judgement_details->action=Select

这些规则只是对所有表执行选择或修改操作。

设计角色

让我们使用我们创建的规则来设计角色。第一个角色是所有警察:

PO_role = server=Myserver->db=db1->table= Driver_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Insert, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details_PO ->action=Insert

请注意,该角色允许所有警官对表

Driver_details

Ticket_details

拥有读/写权限,但只对

Judgement_details

拥有读权限。理由是警察不应该被允许改变判决的细节。您还将观察到警察拥有对

Judgement_details_PO

的写权限,这是为了纠正前两列(没有任何司法信息)——以防有任何错误!

下一个角色是 IT 部门的员工:

IT_role = server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select

IT 员工对所有的表只有读权限,因为他们不允许修改任何数据。

司法机构的作用如下:

JU_role = server=MyServer->db=db1->table= Judgement_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select

judiciary 拥有驾驶员和票证数据的读取权限(因为他们不应该修改这些数据),但拥有输入司法数据的写入权限,因为只有他们才可以修改这些数据。

最后,对于报告机构来说,作用很简单:

RP_role = server=MyServer->db=db1->table=Judgement_details->action=Select

报告机构拥有对

Judgement_details

表的读取权限,只是因为他们被允许报告判决。所有其他数据都是保密的,他们对此没有任何权限。

设置配置文件

我必须为 Sentry 设置各种配置文件,以整合我们之前设置的角色。第一个文件是

sentry-provider.ini

,它定义了每个数据库的策略文件(及其位置)、任何服务器级或数据库级角色,以及 Hadoop 组及其分配的(服务器级或数据库级)角色。下面是

sentry-provider.ini

如何寻找我们的例子:

[databases]
# Defines the location of the per DB policy file for the db1 DB/schema
db1 = hdfs://Master:8020/etc/sentry/customers.ini

[groups]
# Assigns each Hadoop group to its set of roles
db1_admin = db1_admin_role
admin = admin_role

[roles]
# Implies everything on MyServer -> db1\. Privileges for
# db1 can be defined in the global policy file even though
# db1 has its only policy file. Note that the Privileges from
# both the global policy file and the per-DB policy file
# are merged. There is no overriding.
db1_admin_role = server=MyServer->db=db1

# Implies everything on server1
admin_role = server=MyServer

在本例中,数据库

db1

(

customers.ini

)有一个特定的策略文件,并使用其位置进行定义。定义了服务器和数据库

db1

的管理员角色(

admin_role

db1_admin_role

)。适当的 Hadoop 组(

db1_admin

admin

)被分配给这些管理员角色。

下一个文件是

db1.ini

。它是数据库

db1

的每个数据库的策略文件:

[groups]
POfficers = PO_role
ITD = IT_role
Judiciary = JU_role
Reporting = RP_role

[roles]
PO_role = server=MyServer->db=db1->table= Driver_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Insert, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details_PO ->action=Insert

IT_role = server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select, \
server=MyServer->db=db1->table= Judgement_details ->action=Select

JU_role = server=MyServer->db=db1->table= Judgement_details ->action=Insert, \
server=MyServer->db=db1->table= Driver_details ->action=Select, \
server=MyServer->db=db1->table= Ticket_details ->action=Select

RP_role = server=MyServer->db=db1->table=Judgement_details->action=Select

注意上面我已经在

roles

部分定义了所有的角色(之前设计的)。

groups

部分将 Hadoop 组映射到定义的角色。现在,我之前建立了 Hadoop 组

POfficers

ITD

。我将需要建立两个额外的组(

Judiciary

Reporting

),因为我在

db1.ini

文件中为它们映射了角色。

最后一步是设置哨兵配置文件

sentry-site.xml

:

<configuration><property><name>hive.sentry.provider</name><value>org.apache.sentry.provider.file.HadoopGroupResourceAuthorizationProvider</value></property><property><name>hive.sentry.provider.resource</name><value>hdfs://Master:8020/etc/sentry/authz-provider.ini</value></property><property><name>hive.sentry.server</name><value>Myserver</value></property></configuration>

最后,要启用 Sentry,我们需要向

hive-site.xml

添加以下属性:

<property><name>hive.server2.session.hook</name><value>org.apache.sentry.binding.hive.HiveAuthzBindingSessionHook</value></property><property><name>hive.sentry.conf.url</name><value>hdfs://Master:8020/etc/sentry-site.xml</value></property>

这就结束了使用 Apache Sentry 的票务系统示例的重新实现。为我们的票务系统指定正确的授权级别是可能的,因为 Sentry 允许我们定义规则和角色,在必要时限制对数据的访问。如果没有这种灵活性,要么分配太多的访问权限,要么没有访问权限。

摘要

作为为数不多的为 Hadoop 数据提供基于角色的授权的应用程序之一,Sentry 是一个相对较新的版本,仍处于萌芽状态。尽管如此,它在实现基于角色的安全性方面还是提供了一个良好的开端,尽管它远不能与现有的关系数据库技术所提供的安全性相媲美。诚然,Sentry 在提供可与 Oracle 或 Microsoft SQL Server 相媲美的产品方面还有很长的路要走,但目前它是为数不多的可用选项之一。这也是为什么最佳实践是用 Hive 的一些特性来补充哨兵功能的原因!

您可以使用 Hive 来补充和扩展 Sentry 的功能。例如,在票务示例中,我使用 Hive 的外部表特性来创建一个角色,该角色只对表的某些列提供写权限。Sentry 本身不能提供对表的部分写权限,但是您可以将它与 Hive 结合使用来提供这样的权限。我鼓励您研究其他有用的 Hive 特性,并创建自己的角色来扩展 Sentry 的功能。位于

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL

的 Apache 文档提供了许多有用的建议

最后,本章的票务示例证明了您可以通过在 Hive 中定义一个外部表来为角色提供部分数据访问(从第一列开始的列数)。有趣的是,对于一个使用 Sentry 的表,您不能只提供对某些列的访问(例如第四至第八列)。当然,使用 Hive 提供的特性,还有其他方法来实现这样的请求!

标签: VKDoc

本文转载自: https://blog.csdn.net/wizardforcel/article/details/141190543
版权归原作者 绝不原创的飞龙 所有, 如有侵权,请联系我们删除。

“Hadoop 安全实践指南(一)”的评论:

还没有评论