Linkis 权限系统对接

Linkis 权限控制

目前 Linkis 的库表权限控制主要是依赖于 Hive 的权限控制。

下面分享一下 Linkis 接入第三方权限系统,进行库表权限的控制。主要做了三个模块的接入:Metadata 模块、Hive 引擎、Spark 引擎。

以下代码大多为伪代码,需要根据实际情况进行完善,AuthClient 为权限系统的客户端,主要与权限系统交互,获取和校验用户的库表权限。

MetaData 模块对接

前端页面上数据开发面板中,展示的数据库和表是通过调用 linkis-metadata 模块进行获取的,当前的实现是直接查询 Hive 权限相关的表进行获取。

这里需要修改 com.webank.wedatasphere.linkis.metadata.service.impl.DataSourceServiceImpl 类,接入权限系统,根据用户获取有权限的库表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
AuthClient authClient = AuthClient.getInstance();
@Override
public JsonNode getDbs(String userName) throws Exception {
List<String> dbs = authClient.getDbsByUser(userName);
ArrayNode dbsNode = jsonMapper.createArrayNode();
// ...
return dbsNode;
}
@Override
public JsonNode getDbsWithTables(String userName) throws Exception {
ArrayNode dbNodes = jsonMapper.createArrayNode();
List<String> dbs = authClient.getDbsByUser(userName);
// ...
return dbNodes;
}
@Override
public JsonNode queryTables(String database, String userName) {
List<Map<String, Object>> listTables = Lists.newArrayList();
// ...
List<String> authTables = authClient.getTablesByUser(database, userName);

ArrayNode tables = jsonMapper.createArrayNode();
for (Map<String, Object> table : listTables) {
String talbeName = (String) table.get("NAME");
if (!authTables.contains(talbeName)) {
continue;
}
// ...
}
return tables;
}

Hive 引擎对接

Hive 引擎是通过 Hive Driver 进行任务的执行,那么可以通过实现 PreExecute 接口,配置到 hive.exec.pre.hooks 中,完成权限的校验,校验不通过时抛出异常进行拦截。

AuthHiveHook 为 PreExecute 的实现,具体实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class AuthHiveHook extends PreExecute {

def user: String = DWCArgumentsParser.getDWCOptionMap("user")
val authClient: AuthClient = AuthClient.getInstance()

override def run(sess: SessionState, inputs: util.Set[ReadEntity], outputs: util.Set[WriteEntity], ugi: UserGroupInformation): Unit = {
inputs.foreach(input => {
val database = input.getTable.getDbName
val table = input.getTable.getTableName
if (!authClient.checkReadTable(user, database, table)) {
throw new AuthorizationException("Authorization failed, user:" + user + " database:" + database + " table:" + table)
}
})
outputs.foreach(output => {
val database = output.getTable.getDbName
val table = output.getTable.getTableName
if (!authClient.checkWriteTable(user, database, table)) {
throw new AuthorizationException("Authorization failed, user:" + user + " database:" + database + " table:" + table)
}
})
}
}

Spark 引擎对接

Spark 引擎的库表权限控制参考了 spark-authorizer 的实现,通过实现 OptimizerRule,对 LogicalPlan 解析输入输出表,再进行权限校验和控制。