Hadoop 文档

General

Common

HDFS

MapReduce

MapReduce REST APIs

YARN

YARN REST APIs

YARN Service

Submarine

Hadoop Compatible File Systems

Auth

Tools

Reference

Configuration

总览

HDFS实现透明端至端加密。配置完成后,可以透明地加密和解密从特殊HDFS目录读取和写入的数据,而无需更改用户应用程序代码。这种加密也是端到端的,这意味着数据只能由客户端加密和解密。HDFS从不存储或访问未加密的数据或未加密的数据加密密钥。这满足了两个典型的加密要求:静态加密(意味着持久性介质(例如磁盘)上的数据)以及传输中的加密(例如,当数据通过网络传输时)。

背景

可以在传统数据管理软件/硬件堆栈的不同层上进行加密。选择在给定层进行加密有不同的优点和缺点。

  • 应用程序级加密。这是最安全,最灵活的方法。该应用程序对加密内容具有最终控制权,并且可以精确反映用户的需求。但是,编写应用程序来做到这一点很困难。对于不支持加密的现有应用程序的客户,这也不是一种选择。

  • 数据库级加密。就其属性而言,类似于应用程序级加密。大多数数据库供应商都提供某种形式的加密。但是,可能存在性能问题。一个例子是索引不能被加密。

  • 文件系统级加密。此选项提供高性能,应用程序透明性,并且通常易于部署。但是,它无法为某些应用程序级策略建模。例如,多租户应用程序可能希望基于最终用户进行加密。数据库可能希望为单个文件中存储的每个列使用不同的加密设置。

  • 磁盘级加密。易于部署和高性能,但也相当不灵活。只有真正防止物理盗窃。

HDFS级别的加密适合此堆栈中的数据库级别和文件系统级别的加密。这有很多积极的作用。HDFS加密能够提供良好的性能,而现有的Hadoop应用程序能够在加密的数据上透明运行。在制定策略决策时,HDFS还具有比传统文件系统更多的上下文。

HDFS级别的加密还可以防止在文件系统级别及以下的攻击(所谓的“ OS级别攻击”)。操作系统和磁盘仅与加密的字节进行交互,因为数据已由HDFS加密。

用例

许多不同的政府,金融和监管实体都要求数据加密。例如,医疗保健行业有HIPAA法规,卡支付行业有PCI DSS法规,美国政府有FISMA法规。HDFS内置了透明加密,使组织更容易遵守这些法规。

加密也可以在应用程序级别执行,但是通过将其集成到HDFS中,现有应用程序可以对加密数据进行操作而无需更改。这种集成架构意味着更强的加密文件语义以及与其他HDFS功能的更好协调。

建筑

总览

对于透明加密,我们为HDFS引入了新的抽象:加密区域。加密区域是一个特殊的目录,其内容在写入时将被透明加密,在读取时将被透明解密。每个加密区域都与创建该区域时指定的单个加密区域密钥相关联。加密区域内的每个文件都有其自己的唯一数据加密密钥(DEK)。HDF从不直接处理DEK。相反,HDFS仅处理加密的数据加密密钥(EDEK)。客户端解密EDEK,然后使用后续的DEK读取和写入数据。HDFS数据节点仅看到加密字节流。

加密的一个非常重要的用例是“将其打开”并确保整个文件系统中的所有文件都被加密。为了支持这一有力保证,同时又不失去在文件系统不同部分使用不同加密区密钥的灵活性,HDFS允许嵌套加密区。创建加密区域后(例如,在根目录/上),用户可以使用不同的密钥在其后代目录(例如/ home / alice)上创建更多的加密区域。将使用最接近的祖先加密区域的加密区域密钥生成文件的EDEK。

需要新的群集服务来管理加密密钥:Hadoop密钥管理服务器(KMS)。在HDFS加密的情况下,KMS履行三项基本职责:

  1. 提供对存储的加密区域密钥的访问

  2. 生成新的加密数据加密密钥以存储在NameNode上

  3. 解密供HDFS客户端使用的加密数据加密密钥

KMS将在下面更详细地描述。

访问加密区内的数据

在加密区域中创建新文件时,NameNode要求KMS生成使用加密区域的密钥加密的新EDEK。然后,EDEK作为文件元数据的一部分持久存储在NameNode上。

当读取加密区域内的文件时,NameNode为客户端提供文件的EDEK和用于加密EDEK的加密区域密钥版本。然后,客户端要求KMS解密EDEK,这涉及检查客户端是否有权访问加密区域密钥版本。假定成功,则客户端使用DEK解密文件的内容。

读写路径的上述所有上述步骤都是通过DFSClient,NameNode和KMS之间的交互自动发生的。

对加密文件数据和元数据的访问由正常的HDFS文件系统权限控制。这意味着,如果HDFS受到威胁(例如,通过获得对HDFS超级用户帐户的未授权访问),则恶意用户只能获得对密文和加密密钥的访问。但是,由于对加密区域密钥的访问由KMS和密钥存储上的单独权限集控制,因此这不会构成安全威胁。

密钥管理服务器,KeyProvider,EDEK

KMS是代表HDFS守护程序和客户端与后备密钥存储对接的代理。支持密钥库和KMS都实现Hadoop KeyProvider API。有关更多信息,请参见KMS文档

在KeyProvider API中,每个加密密钥都有一个唯一的密钥名称。因为密钥可以滚动,所以一个密钥可以具有多个密钥版本,其中每个密钥版本都有自己的密钥材料(加密和解密过程中使用的实际秘密字节)。可以通过密钥名称,返回密钥的最新版本或特定密钥版本来获取加密密钥。

KMS实现了附加功能,该功能可创建和解密加密的加密密钥(EEK)。EEK的创建和解密完全在KMS上进行。重要的是,请求创建或解密EEK的客户端永远不会处理EEK的加密密钥。为了创建新的EEK,KMS会生成一个新的随机密钥,并使用指定的密钥对其进行加密,然后将EEK返回给客户端。要解密EEK,KMS会检查用户是否有权使用加密密钥,并使用它解密EEK,然后返回解密的加密密钥。

在HDFS加密的上下文中,EEK是加密的数据加密密钥(EDEK),其中数据加密密钥(DEK)用于加密和解密文件数据。通常,密钥库配置为仅允许最终用户访问用于加密DEK的密钥。这意味着EDEK可以由HDFS安全地存储和处理,因为HDFS用户将无法访问未加密的加密密钥。

组态

一个必要的先决条件是KMS的实例,以及KMS的后备密钥存储。有关更多信息,请参见KMS文档

设置KMS并正确配置NameNode和HDFS客户端后,管理员可以使用hadoop密钥hdfs加密命令行工具创建加密密钥并设置新的加密区域。可以使用distcp等工具将现有数据复制到新的加密区域中,从而对现有数据进行加密。

配置集群KeyProvider

hadoop.security.key.provider.path

与读取和写入加密区域时使用的加密密钥进行交互时使用的KeyProvider。HDFS客户端将使用通过getServerDefaults从Namenode返回的提供程序路径。如果namenode不支持返回密钥提供者uri,则将使用客户端的conf。

选择加密算法和编解码器

hadoop.security.crypto.codec.classes.EXAMPLECIPHERSUITE

给定密码编解码器的前缀包含逗号分隔的给定密码编解码器的实现类列表(例如,EXAMPLECIPHERSUITE)。如果可用,将使用第一个实现,其他则是后备。

hadoop.security.crypto.codec.classes.aes.ctr.nopadding

默认值:org.apache.hadoop.crypto.OpensslAesCtrCryptoCodec,org.apache.hadoop.crypto.JceAesCtrCryptoCodec

逗号分隔的AES / CTR / NoPadding加密编解码器实现列表。如果可用,将使用第一个实现,其他则是后备。

hadoop.security.crypto.cipher.suite

默认值:AES / CTR / NoPadding

密码编解码器的密码套件。

hadoop.security.crypto.jce.provider

默认值:无

CryptoCodec中使用的JCE提供程序名称。

hadoop.security.crypto.buffer.size

默认值:8192

CryptoInputStream和CryptoOutputStream使用的缓冲区大小。

Namenode配置

dfs.namenode.list.encryption.zones.num.responses

默认值:100

列出加密区域时,将批量返回的最大区域数。批量增量获取列表可提高名称节点的性能。

加密命令行界面

createZone

用法:[-createZone -keyName <keyName> -path <path>]

创建一个新的加密区域。

路径 要创建的加密区域的路径。它必须是一个空目录。在此路径下设置了垃圾目录。
键名 用于加密区域的密钥名称。不支持大写键名。

listZones

用法:[-listZones]

列出所有加密区域。需要超级用户权限。

供应垃圾

用法:[-provisionTrash -path <路径>]

为加密区域设置垃圾桶目录。

路径 加密区域根的路径。

getFileEncryptionInfo

用法:[-getFileEncryptionInfo -path <路径>]

从文件获取加密信息。这可以用来确定文件是否正在加密,以及用于加密文件的密钥名称/密钥版本。

路径 获取加密信息的文件路径。

reencryptZone

用法:[-reencryptZone <操作>-路径<区域>]

通过遍历加密区域并调用KeyProvider的reencryptEncryptedKeys接口来重新加密加密区域,以使用密钥提供者中的最新版本的加密区域密钥对所有文件的EDEK进行批量重新加密。需要超级用户权限。

请注意,由于快照的不可变性,因此重新加密不适用于快照。

行动 重新加密动作执行。必须为-start-cancel
路径 加密区域根的路径。

重新加密是HDFS中仅使用NameNode的操作,因此可能会对NameNode施加大量负载。可以更改以下配置以控制对NameNode的压力,具体取决于对集群的吞吐量影响。

dfs.namenode.reencrypt.batch.size 批量中要发送到KMS进行重新加密的EDEK数。持有名称系统的读/写锁时,将处理每个批次,并且在批次之间会发生限制。请参阅下面的配置。
dfs.namenode.reencrypt.throttle.limit.handler.ratio 重新加密期间要保留的读取锁的比率。1.0表示没有节流。0.5表示重新加密最多可以将readlock保留其总处理时间的50%。负值或0无效。
dfs.namenode.reencrypt.throttle.limit.updater.ratio 重新加密期间要保留的写锁比率。1.0表示没有节流。0.5表示重新加密可以将写锁最多保留其总处理时间的50%。负值或0无效。

listReencryptionStatus

用法:[-listReencryptionStatus]

列出所有加密区域的重新加密信息。需要超级用户权限。

用法示例

这些说明假定您以适当的普通用户或HDFS超级用户身份运行。根据您的环境使用sudo

#以普通用户身份创建一个新的加密密钥
hadoop密钥创建mykey

#以超级用户身份创建一个新的空目录,并将其设置为加密区域
hadoop fs -mkdir /区域
hdfs crypto -createZone -keyName mykey -path / zone

#普通用户使用
hadoop fs -chown myuser:myuser / zone

#作为普通用户,放入文件,然后读出
hadoop fs -put helloWorld /区域
hadoop fs -cat / zone / helloWorld

#以普通用户的身份从文件中获取加密信息
hdfs crypto -getFileEncryptionInfo -path / zone / helloWorld
#控制台输出:{cipherSuite:{名称:AES / CTR / NoPadding,algorithmBlockSize:16},cryptoProtocolVersion:CryptoProtocolVersion {description ='Encryption zone',version = 1,unknownValue = null},edek:2010d301afbd43b58f10737ce4e93b39,iv:ade2293b :mykey,ezKeyVersionName:mykey @ 0}

Distcp注意事项

以超级用户身份运行

distcp的一种常见用例是在群集之间复制数据,以进行备份和灾难恢复。这通常由作为HDFS超级用户的群集管理员执行。

为了在使用HDFS加密时启用相同的工作流程,我们引入了新的虚拟路径前缀/.reserved/raw/,该前缀使超级用户可以直接访问文件系统中的基础块数据。这使超级用户无需访问加密密钥即可分发数据,并且还避免了解密和重新加密数据的开销。这也意味着源数据和目标数据将是逐字节相同的,如果使用新的EDEK对数据进行了重新加密,那将不是正确的。

使用/.reserved/raw分发加密数据时,使用-px标志保留扩展属性很重要。这是因为加密的文件属性(例如EDEK)是通过/.reserved/raw内的扩展属性公开的,必须保留这些属性才能解密文件。这意味着,如果distcp在加密区域根目录或更高级别启动,则它将在目标位置自动创建一个加密区域(如果尚不存在)。但是,仍然建议管理员首先在目标群集上创建相同的加密区域,以免发生任何潜在的事故。

复制到加密位置

默认情况下,distcp比较文件系统提供的校验和,以验证数据已成功复制到目标。从未加密或加密位置复制到加密位置时,文件系统校验和将不匹配,因为基础块数据不同,因为将使用新的EDEK在目标位置进行加密。在这种情况下,请指定-skipcrccheck-update distcp标志,以避免验证校验和。

重命名和垃圾桶注意事项

HDFS限制跨越加密区域边界的文件和目录重命名。这包括将加密的文件/目录重命名为未加密的目录(例如,hdfs dfs mv / zone / encryptedFile / home / bob),将未加密的文件或目录重命名为加密区域(例如,hdfs dfs mv / home / bob / unEncryptedFile / zone),并在两个不同的加密区域(例如hdfs dfs mv / home / alice / zone1 / foo / home / alice / zone2)之间重命名。在这些示例中,/ zone/ home / alice / zone1/ home / alice / zone2是加密区域,而/ home / bob不是。仅当源路径和目标路径在同一加密区域中,或者两个路径都未加密(不在任何加密区域中)时,才允许重命名。

此限制增强了安全性,并大大简化了系统管理。加密区域下的所有文件EDEK均使用加密区域密钥加密。因此,如果加密区域密钥受到破坏,则重要的是识别所有易受攻击的文件并重新加密它们。如果可以将最初在加密区域中创建的文件重命名为文件系统中的任意位置,则这从根本上来说是困难的。

为了遵守上述规则,每个加密区域在“区域目录”下都有自己的.Trash目录。例如,在hdfs dfs rm / zone / encryptedFile之后,已加密的文件将移至/zone/.Trash,而不是用户主目录下的.Trash目录。删除整个加密区域后,“区域目录”将移动到用户主目录下的.Trash目录。

如果加密区域是根目录(例如/目录),则根目录的回收站路径为/.Trash,而不是用户主目录下的.Trash目录,并且在其中重命名子目录或子文件的行为根目录将与一般加密区域中的行为保持一致,例如本节顶部提到的/ zone

Hadoop 2.8.0之前的crypto命令不会自动设置.Trash目录。如果在Hadoop 2.8.0之前创建了一个加密区域,然后将该集群升级到Hadoop 2.8.0或更高版本,则可以使用-provisionTrash选项(例如hdfs crypto -provisionTrash -path / zone)来配置垃圾桶目录。

攻击向量

硬件访问漏洞

这些漏洞利用假设攻击者已从群集计算机(即数据节点和名称节点)获得了对硬盘驱动器的物理访问。

  1. 访问包含数据加密密钥的进程的交换文件。

    • 就其本身而言,这不会显示明文,因为它还需要访问加密的块文件。

    • 可以通过禁用交换,使用加密交换或使用mlock防止密钥被交换来缓解这种情况。

  2. 访问加密的块文件。

    • 就其本身而言,这不会公开明文,因为它还需要访问DEK。

根访问漏洞

这些漏洞利用是假设攻击者已经获得了对群集计算机(即数据节点和名称节点)的根外壳程序访问权。由于恶意的root用户可以访问持有加密密钥和明文的进程的内存状态,因此无法利用HDFS解决其中的许多漏洞。对于这些攻击,唯一的缓解技术是仔细限制和监视根外壳程序访问。

  1. 访问加密的块文件。

    • 就其本身而言,这不会公开明文,因为它还需要访问加密密钥。
  2. 转储客户端进程的内存以获取DEK,委托令牌,明文。

    • 没有缓解。
  3. 记录网络流量以嗅探加密密钥和传输中的加密数据。

    • 就其本身而言,没有EDEK加密密钥不足以读取明文。
  4. 转储datanode进程的内存以获取加密的块数据。

    • 就其本身而言,没有DEK不足以读取明文。
  5. 转储namenode进程的内存以获取加密的数据加密密钥。

    • 就其本身而言,如果没有EDEK的加密密钥和加密的阻止文件,则不足以读取明文。

HDFS管理员漏洞

这些漏洞利用假设攻击者已经破坏了HDFS,但没有root或hdfs用户外壳程序访问权限。

  1. 访问加密的块文件。

    • 就其本身而言,如果没有EDEK和EDEK加密密钥,则不足以读取明文。
  2. 通过-fetchImage访问加密区域和加密的文件元数据(包括加密的数据加密密钥)。

    • 就其本身而言,没有EDEK加密密钥不足以读取明文。

恶意用户利用

流氓用户可以收集他们有权访问的文件的密钥,并在以后使用它们解密那些文件的加密数据。由于用户可以访问这些文件,因此他们已经可以访问文件内容。这可以通过定期的密钥滚动策略来缓解。该reencryptZone命令通常是关键轧制后要求,以确保在现有文件EDEKs使用新版本的关键。

下面列出了完成密钥滚动和重新加密的手动步骤。这些说明假定您以适当的管理员身份或HDFS超级用户身份运行。

#作为密钥管理员,将密钥滚动到新版本
Hadoop密钥卷暴露密钥

#以超级用户身份重新加密加密区域。可能首先列出区域。
hdfs crypto -listZones
hdfs crypto -reencryptZone-开始-path / zone

#以超级用户身份,定期检查重新加密状态
hdfs crypto -listReencryptionStatus

#以超级用户身份从文件中获取加密信息,并仔细检查其加密密钥版本
hdfs crypto -getFileEncryptionInfo -path / zone / helloWorld
#控制台输出:{cipherSuite:{名称:AES / CTR / NoPadding,algorithmBlockSize:16},cryptoProtocolVersion:CryptoProtocolVersion {description ='Encryption zone',version = 2,unknownValue = null},edek:2010d301afbd43b58f10737ce4e93b39,iv2:ade2Name361 :暴露密钥,ezKeyVersionName:暴露密钥@ 1}