Apache Hadoop 2.9.1
请查看原文:http://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/TransparentEncryption.html
(如果转发,请标明出处)
概述
HDFS实现透明的,端到端(transparent, end-to-end)的加密。配置以后,从特殊HDFS目录读取和写入的数据将透明地加密和解密,而不需要更改用户应用程序代码。这种加密也是端到端的,这意味着数据只能由客户端来进行加密和解密。HDFS从不存储或访问未加密数据或未加密数据加密密钥,这满足了加密的两个典型要求:静态加密(at-rest encryption
)(指永久介质(如磁盘)上的数据)和传输中的加密(in-transit encryption
)(如数据通过网络传输时)。
背景
加密可以在传统数据管理软件/硬件堆栈中的不同层上进行,可以根据不同的优点和缺点选择在给定层进行加密。
① Application-level encryption(应用程序层加密) 。这是最安全最灵活的方法。应用程序对加密内容具有最终控制能力,能够准确反映用户的需求。然而,编写应用程序来做到这一点非常困难,特别对于不支持加密的现有应用程序的客户来说,这不是一个可行选项。
② Database-level encryption(数据库层加密)。属性类似于应用程序层机密。大多数数据库供应商都提供了某种形式的加密,但是,可能存在性能问题。一个反例是索引不能进行加密。
③ Filesystem-level encryption.(文件系统层加密)。此选项提供高性能、应用程序透明性,并且通常易于部署。但是,它无法对某些应用程序级策略进行建模。例如:多租户应用程序可能希望基于最终用户进行加密;数据库可能需要为存储在单个文件中的每个列设置不同的加密设置。
④ Disk-level encryption(硬盘层加密)。易于部署及高性能,但是不灵活,只有真正防止物理盗窃。
HDFS层加密适用于此堆栈中的数据库层和文件系统层加密。这有很多积极的影响。HDFS加密能够提供良好的性能,现有的Hadoop应用程序能够对加密数据透明运行。HDFS在决策时也比传统的文件系统有更多的上下文。
HDFS层加密还可以防止文件系统层和以下层的攻击(所谓的“操作系统层攻击”)。操作系统和磁盘仅与加密字节交互,因为数据已由HDFS加密。
Use Cases
许多不同的政府、金融和监管实体都需要数据加密。例如,医疗保健行业有HIPAA法规,卡支付行业有PCI DSS法规,美国政府有FISMA法规。在HDFS中内置透明加密使组织更容易遵守这些法规。
加密也可以在应用程序层执行,但是通过将它集成到HDFS中,现有的应用程序可以对加密的数据进行操作,而无需更改。这种集成架构意味着更强的加密文件语义和与其他HDFS功能的更好协调。
架构
概述
为了实现透明加密,HDFS引入了一个新的抽象概念:加密区(the encryption zone)。一个加密区就是一个特殊目录,它的内容在写入时透明加密,在读取时透明解密。每个加密区都与创建该区时指定的单个加密区密钥相关联。加密区的每个文件都有自己唯一的加密秘钥(DEK)。DEK不是直接由HDFS处理,相反,HDFS只处理加密数据加密秘钥(encrypted data encryption key EDEK)。客户端解密EDEK,然后使用后续DEK读取和写入数据。HDFS datanode只能看到一个加密字节流。
加密的一个非常重要的用例是“打开它”,并确保整个文件系统中的所有文件都被加密。为了支持这种强有力的保证,同时又不失在文件系统的不同部分使用不同加密区密钥的灵活性,HDFS允许嵌套加密区。当一个加密区被创建后(例如根目录/),用户可以用不同的密钥在其后代目录(例如/home/alice)上创建更多的加密区。文件的EDEK将会使用祖先加密区的加密区密钥生成。
一个新的集群服务是提供密钥管理:the Hadoop Key Management Server (KMS). 在HDFS加密方面,KMS执行三项基本职责:
① 提供对存储的加密区密钥的访问
② 生成新的加密数据加密密钥以存储在NameNode上
③ 为HDFS客户端提供解密使用的加密数据加密密钥
下面将会详细介绍KMS。
访问加密区内的数据
当在一个加密区创建了一个新文件,NameNode 会要求KMS根据加密区秘钥来加密生成一个新的EDEK,EDEK随后会作为文件元数据的一部分永久存储在NameNode上。
当从加密区读取一个文件时,NameNode 会向客户端提供文件的EDEK和用于加密EDEK的加密区密钥版本,客户端接着访问KMS来解密EDEK,这包括检查客户端是否具有访问加密区秘钥版本的权限。假设KMS解密成功,客户端将使用DEK解密文件中的内容。
读写路径的所有上述步骤都是通过DFSClient、NameNode和KMS之间的交互自动进行的。
对加密文件数据和元数据的访问由正常HDFS文件系统权限控制。这意味着,如果HDFS受到危害(例如,通过获得对HDFS超级用户帐户的未授权访问),恶意用户只能获得对密文和加密密钥的访问。但是,由于对加密区域密钥的访问由KMS和密钥存储上的单独权限集控制,因此不会构成安全威胁。
Key Management Server, KeyProvider, EDEKs
KMS是一个代理,代表HDFS后端程序和客户端与备份密钥存储接口。密钥存储和KMS都实现了Hadoop KeyProvider API。有关详细信息,请参阅KMS文档。
在KeyProvider API中,每个加密密钥都有一个唯一的密钥名称。因为密钥可以滚动,所以密钥可以有多个密钥版本,其中每个密钥版本都有自己的密钥材料(加密和解密期间使用的实际秘密字节)。加密密钥可以通过其密钥名称(返回密钥的最新版本)或特定密钥版本来获取。
KMS实现了额外的功能,可以创建和解密加密密钥EEKs ( encrypted encryption keys 缩写为EEKs )。EEKs的创建和解密完全在KMS上进行。重要的是,请求创建或解密EEK的客户端从不处理EEK的加密密钥。要创建新的EEK,KMS将生成一个新的随机密钥,使用指定的密钥对其进行加密,并将EEK返回给客户端。要解密EEK,KMS检查用户是否有权访问加密密钥,使用它来解密EEK,并返回解密的加密密钥。
在HDFS加密的上下文中,EEKs是加密数据加密密钥( EDEKs ),其中数据加密密钥( DEK )是用于加密和解密文件数据的密钥。通常,密钥存储被配置为仅允许最终用户访问用于加密DEKs的密钥。这意味着EDEKs可以由HDFS安全存储和处理,因为HDFS用户将无法访问未加密的加密密钥。
配置
一个必要的先决条件是KMS的实例以及KMS的备份密钥存储。有关详细信息,请参阅KMS文档。
一旦KMS被设置,NameNode和HDFS客户端被正确配置,管理员就可以使用haddoop key和hdfs crypto命令行工具来创建加密密钥和设置新的加密区域。通过使用distcp等工具将现有数据复制到新的加密区,可以对其进行加密。
配置 cluster KeyProvider
① hadoop.security.key.provider.path
读取和写入加密区时,如果需要与使用的加密密钥交互,就需要用到KeyProvider 。HDFS客户端将使用(通过getServerDefaults从Namenode返回的)提供的路径。如果NameNode不支持返回密钥提供程序uri,则将使用客户端的conf。
选择加密算法和codec
① hadoop.security.crypto.codec.classes.EXAMPLECIPHERSUITE
The prefix for a given crypto codec, contains a comma-separated list of implementation classes for a given crypto codec (eg EXAMPLECIPHERSUITE). The first implementation will be used if available, others are fallbacks.
② hadoop.security.crypto.codec.classes.aes.ctr.nopadding
Default: org.apache.hadoop.crypto.OpensslAesCtrCryptoCodec, org.apache.hadoop.crypto.JceAesCtrCryptoCodec
Comma-separated list of crypto codec implementations for AES/CTR/NoPadding. The first implementation will be used if available, others are fallbacks.
③ hadoop.security.crypto.cipher.suite
Default: AES/CTR/NoPadding
Cipher suite for crypto codec.
④ hadoop.security.crypto.jce.provider
Default: None
The JCE provider name used in CryptoCodec.
⑤ hadoop.security.crypto.buffer.size
Default: 8192
The buffer size used by CryptoInputStream and CryptoOutputStream.
Namenode configuration
① dfs.namenode.list.encryption.zones.num.responses
Default: 100
列出加密区域时,批处理中返回的最大区域数。成批递增获取列表可提高NameNode性能。
crypto 命令行接口
createZone
Usage: [-createZone -keyName <keyName> -path <path>]
创建一个新的加密区.
path | The path of the encryption zone to create. It must be an empty directory. A trash directory is provisioned under this path. |
keyName | Name of the key to use for the encryption zone. Uppercase key names are unsupported. |
listZones
Usage: [-listZones]
列出所有加密区,需要超级用户权限.
provisionTrash
Usage: [-provisionTrash -path <path>]
Provision a trash directory for an encryption zone.
path | The path to the root of the encryption zone. |
getFileEncryptionInfo
Usage: [-getFileEncryptionInfo -path <path>]
Get encryption information from a file. This can be used to find out whether a file is being encrypted, and the key name key version used to encrypt it.
path | The path of the file to get encryption information. |
使用范例
这些说明假定您是以正常用户或HDFS超级用户身份运行(如果适用)。根据您的环境需要使用sudo。
hadoop key create mykey
# As the super user, create a new empty directory and make it an encryption zone
hadoop fs -mkdir zone
hdfs crypto -createZone -keyName mykey -path zone
# chown it to the normal user
hadoop fs -chown myuser:myuser zone
# As the normal user, put a file in, read it out
hadoop fs -put helloWorld zone
hadoop fs -cat zone/helloWorld
# As the normal user, get encryption information from the file
hdfs crypto -getFileEncryptionInfo -path zone/helloWorld
# console output: {cipherSuite: {name: AES/CTR/NoPadding, algorithmBlockSize: 16}, cryptoProtocolVersion: CryptoProtocolVersion{description='Encryption zones', version=1, unknownValue=null}, edek: 2010d301afbd43b58f10737ce4e93b39, iv: ade2293db2bab1a2e337f91361304cb3, keyName: mykey, ezKeyVersionName: mykey@0}
Distcp considerations
使用超级用户运行
distcp的一个常见用途是为了备份和故障恢复在集群之间复制数据。这通常由HDFS超级用户集群管理员执行。
为了在使用HDFS加密时启用相同的工作流,我们引入了新的虚拟路径前缀,/.reserved/raw/,它允许超级用户直接访问文件系统中的底层块数据。这允许超级用户在不需要访问加密密钥的情况下对数据进行distcp,也避免了对数据进行解密和重新加密的开销。这也意味着源数据和目标数据将是逐字节相同的,如果数据是用新的EDEK重新加密的那就可能不是逐字节相同了。
使用 /.reserved/raw来distcp加密数据,使用- px flag来保留扩展属性是非常重要的。这是因为加密文件属性(如EDEK )是通过/.reserved/raw中的扩展属性公开的,必须保留才能解密文件。这意味着,如果distcp是在加密区根处或之上启动的,那么如果加密区不存在,它将在目标处自动创建加密区。但是,仍建议管理员首先在目标集群上创建相同的加密区,以避免任何潜在的灾难。
复制到加密位置
默认情况下,distcp会比较文件系统提供的校验和,以验证数据是否已成功复制到目标。当从未加密或加密位置的数据复制到加密位置时,文件系统校验和将不匹配,因为基础块数据不同,也因为新的EDEK将用于在目的地进行加密。在这种情况下,请指定- skipccheck和- update distcp标志,以避免验证校验和。
重命名和删除注意事项(Rename and Trash considerations)
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/zone 1和/home/alice/zone 2是加密区,/home/bob是非加密区。仅当源路径和目标路径位于同一加密区中,或者两个路径都未加密(不在任何加密区中)时,才允许重命名。
这种限制大大提高了安全性,并简化了系统管理。加密区域下的所有文件EDEKs都使用加密区域密钥加密。因此,如果加密区域密钥受损,识别所有易受攻击的文件并重新加密它们是很重要的。如果最初在加密区中创建的文件可以重命名为文件系统中的任意位置,这从根本上说是困难的。
为了符合上述规则,每个加密区在“zone directory”都有自己的 .Trash目录。例如,执行hdfs dfs rm zone/encryptedFile之后,encryptedFile将会被移动到 /zone/.Trash,而不是移动到用户home目录下的 .Trash 目录。当整个的加密区删除后,“zone directory” 将会移动到用户home目录下的 .Trash 目录。
如果加密区是根目录(例如/),则root目录的垃圾路径是 /.Trash,而不是每个用户home目录下的.Trash 目录。重命名根目录中的子目录或子文件的行为将与本节顶部提到的一般加密区(如/ zone )中的行为保持一致。
Hadoop 2.8.0 之前的版本crypto命令没有自动提供.Trash 目录。如果加密区是在Hadoop 2.8.0 版本之前创建的,并且集群需要升级到Hadoop 2.8.0 后者更高版本,则需要使用-provisionTrash来创建trash目录(例如hdfs crypto -provisionTrash -path /zone)。
攻击向量
硬件访问漏洞
这些漏洞假设攻击者已从集群机器(即datanodes and namenodes)获得对硬盘的物理访问。
(1) 访问包含数据加密密钥的进程的交换文件
① 这本身并不公开明文,因为它还需要访问加密的块文件。
② 这可以通过禁用交换、使用加密交换或使用mlock防止密钥被交换来缓解。
(2) 访问加密块文件
① 这本身并不公开明文,因为它也需要访问DEKs。
Root访问漏洞
这些漏洞利用假定攻击者已经获得对集群机器(datanodes and namenodes)的root shell访问。许多这些漏洞无法在HDFS中解决,因为恶意root用户可以访问保存加密密钥和明文的进程的内存中状态。对于这些漏洞,唯一的缓解技术是仔细限制和监视root shell访问。
1 .访问加密的块文件。
这本身并不公开明文,因为它还需要访问加密密钥。
2 .dump 客户端进程的内存以获得DEKs、委托令牌、明文。
没有缓解。
3 .记录网络流量以探测传输中的加密密钥和加密数据。
本身不足以在没有EDEK加密密钥的情况下读取明文。
4 .dump datanode进程的内存以获得加密的块数据。
本身不足以在没有DEK的情况下阅读明文。
5 .dump NameNode进程的内存以获取加密的数据加密密钥。
本身不足以在没有EDEK加密密钥和加密块文件的情况下读取明文。
HDFS管理漏洞
这些漏洞利用假定攻击者已危害HDFS,但没有root或HDFS用户shell 权限。
1 .访问加密的块文件。
本身不足以在没有EDEK和EDEK加密密钥的情况下读取明文。
2 .通过- fetchImage访问加密区和加密文件元数据(包括加密数据加密密钥)。
本身不足以在没有EDEK加密密钥的情况下读取明文。
流氓用户利用
流氓用户可以收集他们有权访问的文件的密钥,并在以后使用它们来解密这些文件的加密数据。由于用户可以访问这些文件,因此他们已经可以访问文件内容。这可以通过周期性的密钥滚动策略来缓解。




