HDFS数据安全与隐私保护

Trash垃圾回收

背景

回收站(垃圾桶)是微软Windows操作系统里的一个系统文件夹,主要用来存放用户临时删除的文档资料,存放在回收站的文件可以恢复。

回收站的功能给了我们一剂“后悔药”。回收站保存了删除的文件、文件夹、图片、快捷方式等。这些项目将一直保留在回收站中,直到您清空回收站。我们许多误删除的文件就是从它里面找到的。

image-20211111200614056

HDFS本身也是一个文件系统,那么就会涉及到文件数据的删除操作。默认情况下,HDFS中是没有回收站垃圾桶概念的,删除操作的数据将会被直接删除,没有后悔药。

image-20211111200622947

功能概述

Trash机制,叫做回收站或者垃圾桶。Trash就像Windows操作系统中的回收站一样。它的目的是防止你无意中删除某些东西。默认情况下是不开启的。

启用Trash功能后,从HDFS中删除某些内容时,文件或目录不会立即被清除,它们将被移动到回收站Current目录中(/user/${username}/.Trash/current)

.Trash中的文件在用户可配置的时间延迟后被永久删除。也可以简单地将回收站里的文件移动到.Trash目录之外的位置来恢复回收站中的文件和目录。

Trash Checkpoint

检查点仅仅是用户回收站下的一个目录,用于存储在创建检查点之前删除的所有文件或目录。如果你想查看回收站目录,可以在/user/${username}/.Trash/{timestamp_of_checkpoint_creation}处看到:

最近删除的文件被移动到回收站Current目录,并且在可配置的时间间隔内,HDFS会为在Current回收站目录下的文件创建检查点/user/${username}/.Trash/<日期>,并在过期时删除旧的检查点。

image-20211111200713877

功能开启

关闭HDFS集群

在node1节点上,执行一键关闭HDFS集群命令:stop-dfs.sh

image-20211111200736944

修改core-site.xml文件

在node1节点上修改core-site.xml文件,添加下面两个属性:

vim /export/server/hadoop-3.1.4/etc/hadoop/core-site.xml

<property>  
    <name>fs.trash.interval</name>  
    <value>1440</value>  
</property>  
<property>  
    <name>fs.trash.checkpoint.interval</name>  
    <value>0</value>  
</property>

fs.trash.interval:分钟数,当超过这个分钟数后检查点会被删除。如果为零,Trash回收站功能将被禁用。

fs.trash.checkpoint.interval:检查点创建的时间间隔(单位为分钟)。其值应该小于或等于fs.trash.interval。如果为零,则将该值设置为fs.trash.interval的值。每次运行检查点时,它都会从当前版本中创建一个新的检查点,并删除在数分钟之前创建的检查点。

同步集群配置文件

scp -r /export/server/hadoop-3.1.4/etc/hadoop/core-site.xml node2:/export/server/hadoop-3.1.4/etc/hadoop/
scp -r /export/server/hadoop-3.1.4/etc/hadoop/core-site.xml node3:/export/server/hadoop-3.1.4/etc/hadoop/

启动HDFS集群

在node1节点上,执行一键启动HDFS集群命令:start-dfs.sh

功能使用

删除文件到Trash

开启Trash功能后,正常执行删除操作,文件实际并不会被直接删除,而是被移动到了垃圾回收站。

image-20211111201225761

当然也可以去Trash回收站下面查看一下:

image-20211111201231960

删除文件跳过Trash

有的时候,我们希望直接把文件删除,不需要再经过Trash回收站了,可以在执行删除操作的时候添加一个参数:-skipTrash.

hadoop fs -rm -skipTrash /smallfile1/3.txt

image-20211111201249257

清空Trash

除了fs.trash.interval参数控制到期自动删除之外,用户还可以通过命令手动清空回收站,释放HDFS磁盘存储空间。

首先想到的是删除整个回收站目录,将会清空回收站,这是一个选择。此外。HDFS提供了一个命令行工具来完成这个工作:

hadoop fs -expunge

该命令立即从文件系统中删除过期的检查点。

Snapshot快照

快照介绍和作用

HDFS snapshot是HDFS整个文件系统,或者某个目录在某个时刻的镜像。该镜像并不会随着源目录的改变而进行动态的更新。可以将快照理解为拍照片时的那一瞬间的投影,过了那个时间之后,又会有新的一个投影。

HDFS快照的核心功能包括:数据恢复、数据备份、数据测试。

数据恢复

可以通过滚动的方式来对重要的目录进行创建snapshot的操作,这样在系统中就存在针对某个目录的多个快照版本。当用户误删除掉某个文件时,可以通过最新的snapshot来进行相关的恢复操作。

数据备份

可以使用snapshot来进行整个集群,或者某些目录、文件的备份。管理员以某个时刻的snapshot作为备份的起始结点,然后通过比较不同备份之间差异性,来进行增量备份。

数据测试

在某些重要数据上进行测试或者实验,可能会直接将原始的数据破坏掉。可以临时的为用户针对要操作的数据来创建一个snapshot,然后让用户在对应的snapshot上进行相关的实验和测试,从而避免对原始数据的破坏。

HDFS快照的实现

在了解HDFS快照功能如何实现之前,首先有一个根本的原则需要记住:快照不是数据的简单拷贝,快照只做差异的记录。这一原则在其他很多系统的快照概念中都是适用的,比如磁盘快照,也是不保存真实数据的。因为不保存实际的数据,所以快照的生成往往非常迅速。

在HDFS中,如果在其中一个目录比如/A下创建一个快照,则快照文件中将会存在与/A目录下完全一致的子目录文件结构以及相应的属性信息,通过命令也能看到快照里面具体的文件内容。但是这并不意味着快照已经对此数据进行完全的拷贝 。这里遵循一个原则:对于大多不变的数据,你所看到的数据其实是当前物理路径所指的内容,而发生变更的inode数据才会被快照额外拷贝,也就是所说的差异拷贝。

inode译成中文就是索引节点,它用来存放文件及目录的基本信息,包含时间、名称、拥有者、所在组等信息。

HDFS快照不会复制datanode中的块,只记录了块列表和文件大小。

HDFS快照不会对常规HDFS操作产生不利影响,修改记录按逆时针顺序进行,因此可以直接访问当前数据。通过从当前数据中减去修改来计算快照数据。

快照的命令

快照功能启停命令

[root@node1 ~]# hdfs dfsadmin
Usage: hdfs dfsadmin
Note: Administrative commands can only be run as the HDFS superuser.
        [-allowSnapshot <snapshotDir>]
        [-disallowSnapshot <snapshotDir>]

HDFS中可以针对整个文件系统或者文件系统中某个目录创建快照,但是创建快照的前提是相应的目录开启快照的功能

如果针对没有启动快照功能的目录创建快照则会报错:

image-20211111201554054

启用快照功能:

hdfs dfsadmin -allowSnapshot /allenwoon

禁用快照功能:

hdfs dfsadmin -disallowSnapshot /allenwoon

快照操作相关命令

[root@node1 ~]# hdfs dfs
Usage: hadoop fs [generic options]
        [-createSnapshot <snapshotDir> [<snapshotName>]]
        [-deleteSnapshot <snapshotDir> <snapshotName>]
        [-renameSnapshot <snapshotDir> <oldName> <newName>]

[root@node1 ~]# hdfs lsSnapshottableDir
[root@node1 ~]# hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot>

快照相关的操作命令有:createSnapshot创建快照、deleteSnapshot删除快照、renameSnapshot重命名快照、lsSnapshottableDir列出可以快照目录列表、snapshotDiff获取快照差异报告。

案例:快照的使用

1、开启指定目录的快照

hdfs dfsadmin -allowSnapshot /allenwoon

image-20211111201650678

2、对指定目录创建快照

hdfs dfs -createSnapshot /allenwoon //系统自动生成快照名称

hdfs dfs -createSnapshot /allenwoon mysnap1 //指定名称创建快照

通过web浏览器访问快照

http://node1:9870/explorer.html#/allenwoon/.snapshot

image-20211111201718786

4、重命名快照

hdfs dfs -renameSnapshot /allenwoon mysnap1 mysnap2

image-20211111201739546

5、列出当前用户所有可以快照的目录

hdfs lsSnapshottableDir

image-20211111201751708

6、比较两个快照不同之处

[root@node1 ~]# echo 222 > 2.txt
[root@node1 ~]# hadoop fs -appendToFile 2.txt /allenwoon/1.txt
[root@node1 ~]# hadoop fs -cat /allenwoon/1.txt
1
222
[root@node1 ~]# hdfs dfs -createSnapshot /allenwoon mysnap3
Created snapshot /allenwoon/.snapshot/mysnap3
[root@node1 ~]# hadoop fs -put zookeeper.out /allenwoon
[root@node1 ~]# hdfs dfs -createSnapshot /allenwoon mysnap4
Created snapshot /allenwoon/.snapshot/mysnap4

hdfs snapshotDiff /allenwoon mysnap2 mysnap3

hdfs snapshotDiff /allenwoon mysnap2 mysnap4

image-20211111201851929

+ The file/directory has been created.

- The file/directory has been deleted.

M The file/directory has been modified.

R The file/directory has been renamed.

7、删除快照

hdfs dfs -deleteSnapshot /allenwoon mysnap4

8、删除有快照的目录

hadoop fs -rm -r /allenwoon

image-20211111201916808

拥有快照的目录不允许被删除,某种程度上也保护了文件安全。

HDFS权限管理

总览概述

作为分布式文件系统,HDFS也集成了一套兼容POSIX的权限管理系统。客户端在进行每次文件操时,系统会从用户身份认证数据访问授权两个环节进行验证: 客户端的操作请求会首先通过本地的用户身份验证机制来获得“凭证”(类似于身份证书),然后系统根据此“凭证”分辨出合法的用户名,再据此查看该用户所访问的数据是否已经授权。一旦这个流程中的某个环节出现异常,客户端的操作请求便会失败。

总览概述

作为分布式文件系统,HDFS也集成了一套兼容POSIX的权限管理系统。客户端在进行每次文件操时,系统会从用户身份认证数据访问授权两个环节进行验证: 客户端的操作请求会首先通过本地的用户身份验证机制来获得“凭证”(类似于身份证书),然后系统根据此“凭证”分辨出合法的用户名,再据此查看该用户所访问的数据是否已经授权。一旦这个流程中的某个环节出现异常,客户端的操作请求便会失败。

image-20211111201953904

UGO权限管理

介绍

HDFS的文件权限与Linux/Unix系统的UGO模型类型类似,可以简单描述为:每个文件和目录都与一个所有者和一个组相关联。该文件或目录对作为所有者(USER)的用户,作为该组成员的其他用户(GROUP)以及对所有其他用户(OTHER)具有单独的权限。

image-20211111202035662

在HDFS中,对于文件,需要r权限才能读取文件,而w权限才能写入或追加到文件。没有x可执行文件的概念。

对于目录,需要r权限才能列出目录的内容,需要w权限才能创建或删除文件或目录,并且需要x权限才能访问目录的子级。

umask权限掩码

Linux中umask可用来设定权限掩码。权限掩码是由3个八进制的数字所组成,将现有的存取权限减掉权限掩码后,即可产生建立文件时预设的权限。

与Linux/Unix系统类似,HDFS也提供了umask掩码,用于设置在HDFS中默认新建的文件和目录权限位。默认umask值有属性fs.permissions.umask-mode指定,默认值022。

创建文件和目录时使用的umask,默认的权限就是:777-022=755。也就是drwxr-xr-x。

UGO权限相关命令

hadoop fs -chmod 750 /user/itcast/foo//变更目录或文件的权限位

hadoop fs -chown :portal /user/itcast/foo //变更目录或文件的属主或用户组

hadoop fs -chgrp itcast _group1 /user/itcast/foo//变更用户组

需要注意的是,使用这个命令的用户必须是超级用户,或者是该文件的属主,同时也是该用户组的成员。

Web页面修改UGO权限

Hadoop3.0之后,支持在HDFS Web页面上使用鼠标修改

image-20211111202210974

粘滞位(Sticky bit)用法在目录上设置,如此以来,只有目录内文件的所有者或者root才可以删除或移动该文件。如果不为目录设置粘滞位,任何具有该目录写和执行权限的用户都可以删除和移动其中的文件。实际应用中,粘滞位一般用于/tmp目录,以防止普通用户删除或移动其他用户的文件。

image-20211111202220197

用户身份认证

用户身份认证独立于HDFS之外,也就说HDFS并不负责用户身份合法性检查,但HDFS会通过相关接口来获取相关的用户身份,然后用于后续的权限管理。用户是否合法,完全取决于集群使用认证体系。目前社区支持两种身份认证,即简单认证(Simple)和Kerberos。模式由hadoop.security.authentication属性指定,默认simple。

Simple认证

基于客户端所在的Linux/Unix系统的登录用户名来进行认证。只要用户能正常登录就认证成功。客户端与NameNode交互时,会将用户的登录账号(通过类似whoami的命令来获取)作为合法用户名传递至Namenode。 这意味着使用不同的账号登录到同一个客户端,会产生不同的用户名,故在多租户条件这种认证会导致权限混淆;同时恶意用户也可以伪造其他人的用户名非法获得相应的权限,对数据安全造成极大的隐患。线上生产环境一般不会使用。simple认证时,HDFS想法是:防止好人误做坏事,不防止坏人做坏事。

image-20211111203012251

image-20211111203015742

Kerberos认证(了解)

在神话里,Kerberos是Cerberus的希腊语,是一只守护地狱入口的三头巨犬,它确保没有人能在进入地狱后离开。

从技术角度来说,Kerberos是麻省理工学院(MIT)开发的一种网络身份认证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。

image-20211111203045323

image-20211111203049150

image-20211111203052585

Group Mapping组映射

在用户身份验证成功之后,接下来会检查该用户所拥有的权限。HDFS的文件权限也是采用UGO模型,分成用户、组和其他权限。但与 Linux/Unix 系统不同,HDFS的用户和组都是使用字符串存储的,在 Linux/Unix上通用的UID和GID是无法在HDFS使用的。

此外,HDFS的组需要通过外部的用户组关联(Group Mapping)服务来获取。用户到组的映射可以使用系统自带的方案(使用NameNode服务器上的用户组系统),也可以通过其他实现类似功能的插件(LDAP、Ranger等)方式来代替。在拿到用户名后,NameNode会通过用户组关联服务获取该用户所对应的用户组列表,并用于后期的用户组权限校验。下面是两种主要的实现方式 。

基于Linux/Unix系统的用户和用户组

Linux/Unix系统上的用户和用户组信息存储在/etc/passwd和/etc/group文件中。默认情况下,HDFS会通过调用外部的 Shell 命令来获取用户的所有用户组列表。 此方案的优点在于组映射服务十分稳定,不易受外部服务的影响。但是用户和用户组管理涉及到root权限等,同时会在服务器上生成大量的用户组,后续管理,特别是自动化运维方面会有较大影响。

image-20211111203213625

基于使用LDAP协议的数据库

OpenLDAP是一个开源LDAP的数据库,通过phpLDAPadmin等管理工具或相关接口可以方便地添加用户和修改用户组。HDFS 可以使用 LdapGroupsMappings 来使用 LDAP 服务。通过配置LDAP的相关属性,可以通过接口来直接获取到某个用户所有的用户组列表(memberOf)。 使用LDAP的不足在于需要保障LDAP服务的可用性和性能,关于LDAP的管理和使用将会后续再作介绍。 不同的LDAP有不同的实现,需要使用不同类型的LDAP Schema来构建,譬如示例中使用的是Person和GroupOfNames类型而不是PosixAccount和PosixGroup类型 以下是开启LDAP关联的配置文件:

<property>
    <name>hadoop.security.group.mapping</name>
    <value>org.apache.hadoop.security.LdapGroupsMapping</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.bind.user</name>
    <value>cn=Manager,dc=hadoop,dc=apache,dc=org</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.bind.password</name>
    <value>hadoop</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.url</name>
    <value>ldap://localhost:389/dc=hadoop,dc=apache,dc=org</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.url</name>
    <value>ldap://localhost:389/dc=hadoop,dc=apache,dc=org</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.base</name>
    <value></value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.search.filter.user</name>
    <value>(&(|(objectclass=person)(objectclass=applicationProcess))(cn={0}))</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.search.filter.group</name>
    <value>(objectclass=groupOfNames)</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.search.attr.member</name>
    <value>member</value>
</property>
<property>
    <name>hadoop.security.group.mapping.ldap.search.attr.group.name</name>
    <value>cn</value>
</property>

ACL权限管理

背景和介绍

在UGO权限中,用户对文件只有三种身份,就是属主(user)、属组(group)和其他人(other):每种用户身份拥有读(read)、写(write)和执行(execute)三种权限。但是在实际工作中,使用UGO来控制权限可以满足大部分场景下的数据安全性要求,但是对于一些复杂的权限需求则无能为力。

image-20211111203339422

文件系统根目录中有一个 /project 目录,这是班级的项目目录。班级中的每个学员都可以访问和修改这个目录,老师也需要对这个目录拥有访问和修改权限,其他班级的学员当然不能访问这个目录。需要怎么规划这个目录的权限呢?应该这样:老师使用 root 用户,作为这个目录的属主,权限为 rwx;班级所有的学员都加入 tgroup 组,使 tgroup 组作为 /project目录的属组,权限是 rwx;其他人的权限设定为 0。这样这个目录的权限就可以符合我们的项目开发要求了。

有一天,班里来了一位试听的学员 st,她必须能够访问/project 目录,所以必须对这个目录拥有 r 和 x 权限;但是她又没有学习过以前的课程,所以不能赋予她 w 权限,怕她改错了目录中的内容,所以学员 st 的权限就是 r-x。可是如何分配她的身份呢?变为属主?当然不行,要不 root 该放哪里?加入 tgroup 组?也不行,因为 tgroup 组的权限是 rwx,而我们要求学员 st 的权限是 r-x。如果把其他人的权限改为 r-x 呢?这样一来,其他班级的所有学员都可以访问 /project 目录了。

当出现这种情况时,普通权限中的三种身份就不够用了。ACL 权限就是为了解决这个问题的。在使用 ACL 权限给用户 st 陚予权限时,st 既不是 /project 目录的属主,也不是属组,仅仅赋予用户 st 针对此目录的 r-x 权限。

ACL是Access Control List(访问控制列表)的缩写,ACL提供了一种方法,可以为特定的用户或组设置不同的权限,而不仅仅是文件的所有者和文件的组

ACL Shell命令

hadoop fs -getfacl [-R] <path>

显示文件和目录的访问控制列表(ACL)。如果目录具有默认ACL,则getfacl还将显示默认ACL。

hadoop fs [generic options] -setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>]|[--set <acl_spec> <path>]

设置文件和目录的访问控制列表(ACL)。

hadoop fs -ls <args>

ls的输出将在带有ACL的任何文件或目录的权限字符串后附加一个’+’字符。

ACL操作实战

Root用户创建文件夹: hadoop fs -mkdir /itheima
此时使用普通用户allenwoon去操作/itheima 发现没有w权限

[allenwoon@node1 ~]$ echo 1 >> 1.txt
[allenwoon@node1 ~]$ hadoop fs -put 1.txt /itheima
put: Permission denied: user=allenwoon, access=WRITE, inode="/itheima":root:supergroup:drwxr-xr-x

接下来使用ACL给allenwoon用户单独添加rwx权限

hadoop fs -setfacl -m user:allenwoon:rwx /itheima
setfacl: The ACL operation has been rejected.  Support for ACLs has been disabled by setting dfs.namenode.acls.enabled to false.

发现报错 原因是ACl功能默认是关闭的。
在hdfs-site.xml中设置dfs.namenode.acls.enabled=true 开启ACL 重启HDFS集群

再次设置ACl权限
hadoop fs -setfacl -m user:allenwoon:rwx /itheima

设置成功之后查看ACL权限
hadoop fs -getfacl /itheima

[root@node1 ~]# hadoop fs -getfacl /itheima
# file: /itheima
# owner: root
# group: supergroup
user::rwx
user:allenwoon:rwx     发现allenwoon权限配置成功
group::r-x
mask::rwx
other::r-x

再使用普通用户allenwoon去操作,发现可以成功了
如果切换其他普通用户 发现还是无法操作

[itcast@node2 ~]$ echo 2 >> 2.txt
[itcast@node2 ~]$ hadoop fs -put 2.txt /itheima
put: Permission denied: user=itcast, access=WRITE, inode="/itheima":root:supergroup:drwxrwxr-x
----------------------------------------

ACL其他操作命令

1、带有ACL的任何文件或目录的权限字符串后附加一个’+’字符

[root@node1 ~]# hadoop fs -ls /
Found 5 items
drwxr-xr-x   - root supergroup          0 2021-01-06 20:59 /data
drwxr-xr-x   - root supergroup          0 2020-12-31 11:59 /itcast
drwxrwxr-x+  - root supergroup          0 2021-01-07 19:38 /itheima
drwx------   - root supergroup          0 2020-12-31 11:56 /tmp
drwxr-xr-x   - root supergroup          0 2020-12-31 11:56 /user

2、删除指定的ACL条目
hadoop fs -setfacl -x user:allenwoon /itheima

3、删除基本ACL条目以外的所有条目。保留用户,组和其他条目以与权限位兼容。
hadoop fs -setfacl -b /itheima

4、设置默认的ACl权限,以后在该目录中新建文件或者子目录时,新建的文件/目录的ACL权限都是之前设置的default ACLs

[root@node1 ~]# hadoop fs -setfacl -m default:user:allenwoon:rwx /itheima
[root@node1 ~]# hadoop fs -getfacl /itheima                              
# file: /itheima
# owner: root
# group: supergroup
user::rwx
group::r-x
other::r-x
default:user::rwx
default:user:allenwoon:rwx
default:group::r-x
default:mask::rwx
default:other::r-x

5、删除默认ACL权限
hadoop fs -setfacl -k /itheima

6、—set: 完全替换ACL,丢弃所有现有条目。 acl_spec必须包含用户,组和其他条目,以便与权限位兼容。
hadoop fs -setfacl --set user::rw-,user:hadoop:rw-,group::r--,other::r-- /file

HDFS Proxy user代理用户

介绍

Proxy user描述的是超级用户如何代表另一个用户提交作业或访问HDFS

比如:用户名为“super”的超级用户希望代表用户joe提交作业并访问hdfs。因为超级用户具有kerberos凭证,但joe用户没有任何凭证。这些任务需要以用户joe的身份运行,而对namenode的任何文件访问都必须以用户joe的身份进行。要求用户joe可以在通过super的kerberos凭据进行身份验证的连接上连接到namenode。换句话说,super正在冒充用户joe。

使用示例

...
  //为joe创建ugi。登录用户为“超级”。
  UserGroupInformation ugi =
          UserGroupInformation.createProxyUser(“ joe”,UserGroupInformation.getLoginUser());
  ugi.doAs(new PrivilegedExceptionAction <Void>(){
    public Void run()引发异常{
      //提交工作
      JobClient jc = new JobClient(conf);
      jc.submitJob(conf);
      //或访问hdfs
      FileSystem fs = FileSystem.get(conf);
      fs.mkdir(someFilePath);
    }
  }

在此示例中,super的凭据用于登录,并为joe创建了代理用户ugi对象。在此代理用户ugi对象的doAs方法内执行操作。

配置参数

可以通过在core-site.xml中使用下面属性来配置代理用户:

hadoop.proxyuser.$superuser.hosts

hadoop.proxyuser.$superuser.groups

hadoop.proxyuser.$superuser.users

例如:名为super的超级用户只能从host1和host2连接来模拟属于group1和group2的用户。

<property>
     <name>hadoop.proxyuser.super.hosts</name>
     <value>host1,host2</value>
</property>
<property>
     <name>hadoop.proxyuser.super.groups</name>
     <value>group1,group2</value>
</property>

如果不存在这些配置,则将无法进行模拟并且连接将失败。

还有更加宽松的配置,通配符*可用于允许来自任何主机或任何用户的模拟。例如,通过在core-site.xml中进行如下指定,从任何主机访问的名为oozie的用户都可以假冒属于任何组的任何用户。

<property>
    <name>hadoop.proxyuser.oozie.hosts</name>
    <value>*</value>
</property>
<property>
    <name>hadoop.proxyuser.oozie.groups</name>
    <value>*</value>
</property>

注意事项

如果集群以安全模式运行,则超级用户必须具有kerberos凭据才能模拟其他用户。

它不能为此功能使用委托令牌。如果超级用户将自己的委派令牌添加到代理用户ugi,那将是错误的,因为它将允许代理用户使用超级用户的特权连接到服务。

但是,如果超级用户确实希望将委派令牌授予joe,则它必须首先模拟joe并获得joe的委派令牌,与上面的代码示例相同,然后将其添加到joe的ugi中。这样,委派令牌将拥有者为joe。

HDFS Transparent Encryption透明加密

HDFS明文存储弊端

HDFS中的数据会以block的形式保存在各台数据节点的本地磁盘中,但这些block都是明文的,如果在操作系统下,直接访问block所在的目录,通过Linux的cat命令是可以直接查看里面的内容的,而且是明文。

image-20211111204304083

下面我们直接去DataNode本地存储block的目录,直接查看block内容:

/export/data/hadoop-3.1.4/dfs/data/current/BP-1748151750-192.168.227.151-1608259905540/current/finalized/subdir0/subdir0/

image-20211111204319387

背景和应用

常见的加密层级

  • 应用层加密

这是最安全也是最灵活的方式。加密内容最终由应用程序来控制,并且可以精确的反映用户的需求。但是,编写应用程序来实现加密一般都比较困难。

  • 数据库层加密

类似于应用程序加密。大多数数据库厂商都提供某种形式的加密,但是可能会有性能问题,另外比如说索引没办法加密。

  • 文件系统层加密

这种方式对性能影响不大,而且对应用程序是透明的,一般也比较容易实施。但是应用程序细粒度的要求策略,可能无法完全满足。

  • 磁盘层加密

易于部署和高性能,但是相当不灵活,只能防止用户从物理层面盗窃数据。

HDFS的透明加密属于数据库层和文件系统层的加密。拥有不错的性能,且对于现有的应用程序是透明的。HDFS加密可以防止在文件系统或之下的攻击,也叫操作系统级别的攻击(OS-level attacks)。操作系统和磁盘只能与加密的数据进行交互,因为数据已经被HDFS加密了。

应用场景

数据加密对于全球许多政府,金融和监管机构都是强制性的,以满足隐私和其他安全要求。例如,卡支付行业已采用“支付卡行业数据安全标准”(PCI DSS)来提高信息安全性。其他示例包括美国政府的《联邦信息安全管理法案》(FISMA)和《健康保险可移植性和责任法案》(HIPAA)提出的要求。加密存储在HDFS中的数据可以帮助您的组织遵守此类规定。

透明加密介绍

HDFS透明加密(Transparent Encryption)支持端到端的透明加密,启用以后,对于一些需要加密的HDFS目录里的文件可以实现透明的加密和解密,而不需要修改用户的业务代码。端到端是指加密和解密只能通过客户端。对于加密区域里的文件,HDFS保存的即是加密后的文件,文件加密的秘钥也是加密的。让非法用户即使从操作系统层面拷走文件,也是密文,没法查看。

image-20211111204434477

HDFS透明加密具有以下功能特点:

  • 只有HDFS客户端可以加密或解密数据。
  • 密钥管理在HDFS外部。HDFS无法访问未加密的数据或加密密钥。HDFS的管理和密钥的管理是独立的职责,由不同的用户角色(HDFS管理员,密钥管理员)承担,从而确保没有单个用户可以不受限制地访问数据和密钥。
  • 操作系统和HDFS仅使用加密的HDFS数据进行交互,从而减轻了操作系统和文件系统级别的威胁。
  • HDFS使用高级加密标准计数器模式(AES-CTR)加密算法。AES-CTR支持128位加密密钥(默认),或者在安装Java Cryptography Extension(JCE)无限强度JCE时支持256位加密密钥。

透明加密关键概念和架构

加密区域和密钥

HDFS的透明加密有一个新的概念,加密区域(the encryption zone)。加密区域是一个特殊的目录,写入文件的时候会被透明加密,读取文件的时候又会被透明解密。

当加密区域被创建时,都会有一个加密区域秘钥EZ密钥,encryption zone key)与之对应,EZ密钥存储在HDFS外部的备份密钥库中。加密区域里的每个文件都有其自己加密密钥,叫做数据加密秘钥DEK,data encryption key)。DEK会使用其各自的加密区域的EZ密钥进行加密,以形成加密数据加密密钥(EDEK)HDFS不会直接处理DEK,HDFS只会处理EDEK。客户端会解密EDEK,然后用后续的DEK来读取和写入数据。

关于EZ密钥、DEK、EDEK三者关系如下所示:

image-20211111204518409

Keystore和Hadoop KMS

存储密钥(key)的叫做密钥库(keystore),将HDFS与外部企业级密钥库(keystore)集成是部署透明加密的第一步。这是因为密钥(key)管理员和HDFS管理员之间的职责分离是此功能的非常重要的方面。但是,大多数密钥库都不是为Hadoop工作负载所见的加密/解密请求速率而设计的。

为此,Hadoop进行了一项新服务的开发,该服务称为Hadoop密钥管理服务器(Key Management Server,简写KMS),该服务用作HDFS客户端与密钥库之间的代理。密钥库和Hadoop KMS相互之间以及与HDFS客户端之间都必须使用Hadoop的KeyProvider API进行交互。

KMS主要有以下几个职责:

1.提供访问保存的加密区域秘钥(EZ key)

2.生成EDEK,EDEK存储在NameNode上

3.为HDFS客户端解密EDEK

访问加密区域内的文件

写入加密文件过程

image-20211111204601504

前提:创建HDFS加密区时会创建一个HDFS加密区(目录),同时会在KMS服务里创建一个key及其EZ Key,及两者之间的关联。

1.Client向NN请求在HDFS某个加密区新建文件;

2.NN向KMS请求此文件的EDEK,KMS用对应的EZ key生成一个新的EDEK发送给NN;

3.这个EDEK会被NN写入到文件的metadata中;

4.NN发送EDEK给Client;

5.Client发送EDEK给KMS请求解密,KMS用对应的EZ key将EDEK解密为DEK发送给Client;

6.Client用DEK加密文件内容发送给datanode进行存储。

DEK是加解密一个文件的密匙,而KMS里存储的EZ key是用来加解密所有文件的密匙(DEK)的密匙。所以,EZ Key是更为重要的数据,只在KMS内部使用(DEK的加解密只在KMS内存进行),不会被传递到外面使用,而HDFS服务端只能接触到EDEK,所以HDFS服务端也不能解密加密区文件。

读取解密文件过程

读流程与写流程类型,区别就是NN直接读取加密文件元数据里的EDEK返回给客户端,客户端一样把EDEK发送给KMS获取DEK。再对加密内容解密读取。

EDEK的加密和解密完全在KMS上进行。更重要的是,请求创建或解密EDEK的客户端永远不会处理EZ密钥。仅KMS可以根据要求使用EZ密钥创建和解密EDEK。

KMS配置

关闭HDFS集群

在node1上执行stop-dfs.sh。

key密钥生成

[root@node1 ~]# keytool -genkey  -alias 'itcast'
Enter keystore password:  
Re-enter new password: 
What is your first and last name?
  [Unknown]:  
What is the name of your organizational unit?
  [Unknown]:  
What is the name of your organization?
  [Unknown]:  
What is the name of your City or Locality?
  [Unknown]:  
What is the name of your State or Province?
  [Unknown]:  
What is the two-letter country code for this unit?
  [Unknown]:  
Is CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown correct?
  [no]:  yes
Enter key password for <itcast>
        (RETURN if same as keystore password):  
Re-enter new password:

image-20211111204752422

配置kms-site.xml

配置文件路径:/export/server/hadoop-3.1.4/etc/hadoop/kms-site.xml

<configuration>

	<property>
		<name>hadoop.kms.key.provider.uri</name>
		<value>jceks://file@/${user.home}/kms.jks</value>
	</property>

	<property>
		<name>hadoop.security.keystore.java-keystore-provider.password-file</name>
		<value>kms.keystore.password</value>
	</property>
 
	<property>
		 <name>dfs.encryption.key.provider.uri</name>
		 <value>kms://http@node1:16000/kms</value>
	</property>

	<property>
		<name>hadoop.kms.authentication.type</name>
		<value>simple</value>
	</property>
 
</configuration>

密码文件通过类路径在Hadoop的配置目录中查找。

kms-env.sh

export KMS_HOME=/export/server/hadoop-3.1.4
export KMS_LOG=${KMS_HOME}/logs/kms
export KMS_HTTP_PORT=16000
export KMS_ADMIN_PORT=16001

修改core|hdfs-site.xml

core-site.xml

<property>
    <name>hadoop.security.key.provider.path</name>
    <value>kms://http@node1:16000/kms</value>
</property>

hdfs-site.xml

<property>
    <name>dfs.encryption.key.provider.uri</name>
    <value>kms://http@node1:16000/kms</value>
</property>

同步配置文件

cd /export/server/hadoop-3.1.4/etc/hadoop/
scp core-site.xml hdfs-site.xml node2.itcast.cn:/export/server/hadoop-3.1.4/etc/hadoop/
scp core-site.xml hdfs-site.xml node3.itcast.cn:/export/server/hadoop-3.1.4/etc/hadoop/
scp kms-site.xml node2.itcast.cn:/export/server/hadoop-3.1.4/etc/hadoop/
scp kms-site.xml node3.itcast.cn:/export/server/hadoop-3.1.4/etc/hadoop/
scp kms-env.sh node2.itcast.cn:/export/server/hadoop-3.1.4/etc/hadoop/
scp kms-env.sh node3.itcast.cn:/export/server/hadoop-3.1.4/etc/hadoop/

服务启动

KMS服务启动

hadoop --daemon start kms

image-20211111205025414

HDFS集群启动

start-dfs.sh

透明加密使用

创建key

切换成普通用户allenwoon操作

su allenwoon
hadoop key create itcast 
hadoop key list -metadata

image-20211111205145221

创建加密区

使用root超级用户操作

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

image-20211111205231653

#将其chown给普通用户
hadoop fs -chown allenwoon:allenwoon /zone

测试加密效果

以普通用户操作

#以普通用户的身份放入文件,然后读出来
echo helloitcast >> helloWorld
hadoop fs -put helloWorld /zone 
hadoop fs -cat /zone /helloWorld 

#作为普通用户,从文件获取加密信息
hdfs crypto -getFileEncryptionInfo -path /zone/helloWorld 

image-20211111205307829

直接下载文件的block 发现是无法读取数据的。

image-20211111205316958