所有文章 > API安全 > WebHDFS Rest API 企业实战:大佬手把手带你堵住漏洞,企业实例解析

WebHDFS Rest API 企业实战:大佬手把手带你堵住漏洞,企业实例解析

Apache Hadoop提供了本地库,用于访问HDFS。这些本地库对于在Hadoop集群内运行的应用程序非常有用,只需要配置hadoop客户端的环境就可以使用这些库来直接访问HDFS。

        然而,对于外部应用程序来说,如果需要与HDFS集群进行交互。比如常见的创建目录、将文件写入新目录,读取存储在HDFS中的文件内容。甚至设置HDFS文件权限,此时如果程序所在的环境没有Hadoop的本地库,也就无法实现这些需求。这就是为什么您需要使用WEBHDFS REST API的原因。它提供了一种机制,使外部应用程序能够与HDFS数据进行交互。通过使用WEBHDFS REST API,外部应用程序可以通过HTTP请求来执行各种操作,如创建目录、上传文件、读取文件等,从而实现与HDFS的交互。

       WEBHDFS是一个 REST API,支持 GET POST、PUT 和 DELETE 等 HTTP 操作。它允许客户端应用程序通过 HTTP 或 HTTPs 访问 HDFS 数据并执行 HDFS 操作。它具有以下功能:

  • 读写访问 – REST API 支持HDFS 的完整FileSystem / FileContext接口,包括授予权限、访问块位置、配置复制因子等 。 
  • HDFS 参数 – 它支持所有 HDFS 参数及其默认值。
  • 身份验证 – 此 REST API 使用 Hadoop 和 Kerberos 来验证请求。当安全性开启时,将使用 Kerberos。 
  • 多语言-允许客户端使用不同语言访问HDFS,而无需安装Hadoop。它还可以与wget、curl等工具配合使用来访问HDFS。 
  • 开源-它是一个完全开源的工具。

1.配置REST API

启用此功能操作上非常的简单,只需要简单的配置即可,在hdfs-site.xml文件中添加下面的配置项。

<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>

在CDH中启用:(默认是开启的)

注意:

  • 这个虽然是默认开启的,但是在没有启用kerberos等安全认证措施的情况下开启的风险很大,客户端可以模拟任何用户来操作集群,可以删除集群所有数据。
  • 直接关闭带来的影响就是无法通过namenode的web页面查看集群数据,或者直接打不开active状态的namenode的web

端口配置:

WEBHDFS REST API使用的端口是WebHDFS默认端口,通常为50070(HTTP)或50470(HTTPS)。这些端口可以通过Hadoop配置文件进行自定义设置。在配置文件中,dfs.namenode.http-address指定了HTTP端口,dfs.namenode.https-address指定了HTTPS端口。具体的端口配置取决于Hadoop集群的设置和管理员的配置。

2.REST API请求方式

支持 FileSystem URIs 和 HTTP URLs

  1. FileSystem scheme 是”webhdfs://”,格式如下:
webhdfs://<HOST>:<HTTP_PORT>/<PATH>

这个可以和和常用的HDFS的URl对比,格式如下:

hdfs://<HOST>:<RPC_PORT>/<PATH>

两者之间的区别主要在于通信协议和端口:

  • HDFS的URL使用的是”hdfs” scheme,而WebHDFS使用的是”webhdfs” scheme。
  • HDFS的URL使用的是RPC端口(默认为8020),而WebHDFS使用的是HTTP端口(默认hadoop2是 50070,hadoop3是 9870)。

2.HTTP URl格式是:,请求的方式如下

http://<HOST>:<HTTP_PORT>/webhdfs/v1/<PATH>?op=...

REST API中,完整的路径中需要插入了前缀”/webhdfs/v1″,并在末尾附加了查询。因此,完整相应的HTTP URL具有以下格式:

http://<namenode>:<port>/webhdfs/v1/<path>?<query>
  • <namenode>是HDFS Namenode的主机名或IP地址。
  • <port>是Namenode的WebHDFS服务运行的端口号(HTTP默认为50070,HTTPS默认为50470)。
  • <path>是要进行交互的HDFS文件或目录的路径。
  • <query>是查询参数,用于指定操作、用户、权限等。

例如,要访问根目录中名为 “example.txt” 的文件,则相应的URL可能如下所示:

http://<namenode>:<port>/webhdfs/v1/example.txt?op=OPEN&user.name=<username>

在上面的示例中,<op>是操作参数,user.name是指定访问文件的用户的查询参数。请注意,实际的URL和查询参数将根据具体操作和需求而有所不同。

3.REST API具体使用

3.1 文件增删改查

  1. 查看指定目录的状态
curl -s "http://ds-bigdata-001:9870/webhdfs/v1/tmp?user.name=aqiang&op=GETFILESTATUS" | jq

这个命令使用curl发送HTTP GET请求到指定的URL。URL是http://ds-bigdata-001:9870/webhdfs/v1/tmp?user.name=aqiang&op=GETFILESTATUS

其中包括了查询参数user.nameop

-s选项用于禁用curl的进度条显示。

然后,通过管道将curl的输出传递给jq命令。jq是一个命令行工具,用于处理JSON数据。

运行该命令后,curl会向指定URL发送请求,并获取到JSON响应。然后,这个JSON响应会被传递给jq命令进行处理。jq会对JSON进行解析和格式化,并将格式化后的结果输出到终端上。

2.创建目录

curl -i -X PUT "http://ds-bigdata-001:9870/webhdfs/v1/tmp/test_webhdfs_dir?user.name=aqiang&op=MKDIRS"

这里通过api在/tmp目录下新建一个目录test_webhdfs_dir。

验证已经创建成功;

3.读取文件

curl  -L "http://ds-bigdata-001:9870/webhdfs/v1/tmp/test_webhdfs_dir/1.txt?op=OPEN&user.name=aqiang"

这里提前在指定目录下放一个1.txt的文件。下面成功读取到文件的内容。

4.删除文件

curl -i -X DELETE "http://ds-bigdata-001:9870/webhdfs/v1/tmp/test_webhdfs_dir/1.txt?op=DELETE&user.name=aqiang"

3.2 文件权限管理

权限管理上,一般操作比较多的就是文件的ACL条目设置,具体的一些相关操作总结如下:

WebHDFS REST API 操作ACL

## 以curl请求为例:
curl -i -X PUT "http://<HOST>:<PORT>/webhdfs/v1/<PATH>?op=MODIFYACLENTRIES&aclspec=<ACLSPEC>"
curl -i -X PUT "http://<HOST>:<PORT>/webhdfs/v1/<PATH>?op=REMOVEACLENTRIES&aclspec=<ACLSPEC>"
curl -i -X PUT "http://<HOST>:<PORT>/webhdfs/v1/<PATH>?op=REMOVEACL"
curl -i -X PUT "http://<HOST>:<PORT>/webhdfs/v1/<PATH>?op=GETACLSTATUS"

ACLSPEC 格式如下:【ACL权限规范中的每个条目都要符合下面格式要求,多个条目之前使用逗号分隔.

^(default:)?(user|group|mask|other):[[A-Za-z_][A-Za-z0-9._-]]*:([rwx-]{3})?(,(default:)?(user|group|mask|other):[[A-Za-z_][A-Za-z0-9._-]]*:([rwx-]{3})?)*$
(default:)?:可选的前缀,表示默认权限。
(user|group|mask|other):指定条目的类型,可以是用户、组、掩码或其他。
[[A-Za-z_][A-Za-z0-9._-]]*:条目的名称,可以是字母、数字、下划线、点或破折号组成。
([rwx-]{3})?:可选的权限部分,表示读、写和执行权限。

1. 添加(修改)acl;可以修改已有的acl和添加新的acl权限

curl -i -X PUT "http://ds-bigdata-001:9870/webhdfs/v1/mobtttt?user.name=hdfs&op=MODIFYACLENTRIES&aclspec=user:test555:rwx,user:test6666:rw-,group:mob:r-x"
  1. http://ds-bigdata-001:9870WebHDFS服务的地址和端口。
  2. /webhdfs/v1/mobtttt:要修改ACL权限的目录路径。
  3. user.name=hdfs:指定代理用户为hdfs
  4. op=MODIFYACLENTRIES:指定操作为修改ACL权限。
  5. aclspec=user:test555:rwx,user:test6666:rw-,group:mob:r-x:指定ACL权限规范,其中包含要修改的ACL条目。
    1. user:test555:rwx:用户test555具有读、写和执行权限。
    2. user:test6666:rw-:用户test6666具有读和写权限,但无执行权限。
    3. group:mob:r-x:组mob的成员具有读和执行权限,但无写权限。

说明:此条指令是同时添加多条acl条目,多条用逗号隔

2.删除指定的acl条目

curl -i -X PUT "http://ds-bigdata-001:9870/webhdfs/v1/mobtttt?user.name=hdfs&op=REMOVEACLENTRIES&aclspec=user:test6666:,group:mob:"
  1. op=REMOVEACLENTRIES:指定操作为删除ACL权限。
  2. aclspec=user:test6666:,group:mob::指定ACL权限规范,其中包含要删除的ACL条目。
    1. user:test6666::删除用户test6666的ACL条目。
    2. group:mob::删除组mob的ACL条目。

说明:可以同时删除一条或者多条,多条用逗号分割。

3.删除所有的acl条目

curl -i -X PUT "http://ds-bigdata-001:9870/webhdfs/v1/mobtttt?user.name=hdfs&op=REMOVEACL"

4.获取acl条目

curl -i -X get http://ds-bigdata-001:9870/webhdfs/v1/mobtttt?op=GETACLSTATUS

tips:WEBHDFS Rest API 一般可以配合自动化脚本等场景来使用。

4.示例分享

在有些场景下,我们可能只需要ACL相关的设置功能,此时可以修改源码或者自定义一个新的接口去实现。下面是一个仅供参考的示例demo。

4.1 自定义接口(python+hdfs shell)

from flask import Flask, request
import subprocess

app = Flask(__name__)

@app.route('/hdfs/acl', methods=['POST'])
def set_acl():
path = request.form.get('path')
acl = request.form.get('acl')

try:
command = ['hdfs', 'dfs', '-setfacl', '-R', '-m', acl, path]
subprocess.run(command, check=True)
print(command)
return 'ACL set successfully'
except subprocess.CalledProcessError as e:
return 'Failed to set ACL: ' + str(e), 500

@app.route('/hdfs/acl', methods=['DELETE'])
def remove_acl():
path = request.form.get('path')

try:
command = ['hdfs', 'dfs', '-setfacl', '-R', '-b', path]
subprocess.run(command, check=True)
print(command)
return 'ACL removed successfully'
except subprocess.CalledProcessError as e:
return 'Failed to remove ACL: ' + str(e), 500

@app.route('/hdfs/acl', methods=['GET'])
def get_acl():
path = request.args.get('path')

try:
command = ['hdfs', 'dfs', '-getfacl', '-R', path]
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
print(command)
return result.stdout
except subprocess.CalledProcessError as e:
return 'Failed to get ACL: ' + str(e), 500

if __name__ == '__main__':
app.run(host='0.0.0.0', port=8099)
接口名称:HDFS ACL 接口
接口描述:该接口用于操作HDFS的ACL,包括设置ACL、删除ACL和获取ACL信息。
接口URL:`http://xxx:8099/hdfs/acl`
接口支持的HTTP方法:
- 设置ACL:POST
- 删除ACL:DELETE
- 获取ACL:GET
参数说明:
1. 设置ACL(POST请求):
- 参数名:
- `path`:HDFS路径,表示要设置ACL的文件或目录的路径。
- `acl`:ACL字符串,表示要设置的ACL规则。ACL规则的格式请参考HDFS ACL规范。
2. 删除ACL(DELETE请求):
- 参数名:
- `path`:HDFS路径,表示要删除ACL的文件或目录的路径。
3. 获取ACL(GET请求):
- 参数名:
- `path`:HDFS路径,表示要获取ACL的文件或目录的路径。
响应格式:
- 设置ACL和删除ACL接口的响应格式为纯文本,包含成功或失败的消息。
- 获取ACL接口的响应格式为ACL信息的文本形式。
访问权限:
- 外部用户需要具有HDFS操作权限,并能够从访问该接口的主机访问到HDFS集群。
说明:在hdfs文件系统的集群的客户端节点,使用hdfs用户启动接口服务。

错误处理:
- 当设置ACL、删除ACL或获取ACL接口发生错误时,会返回适当的错误消息和HTTP状态码。请根据状态码和错误消息进行错误处理。
# CURl 请求示例:
修改目录/test ACL
curl -X POST -d "path=/test&acl=user:test:rwx" http://localhost:8099/hdfs/acl
删除ACL
curl -X DELETE -d "path=/test" http://localhost:8099/hdfs/acl
获取ACL
curl -X GET 'http://localhost:8099/hdfs/acl?path=/test'

本文章转载微信公众号@涤生大数据

#你可能也喜欢这些API文章!