为了保证系统的安全性,Azkaban向用户提供了一种采用Executor机器上的Linux用户执行job的方式,即execute-as-user。本文将说明Azkaban如何配置execute-as-user,并且修改Azkaban源代码,默认禁用user-to-proxy,强制Azkaban用户以当前身份提交作业。
1. 创建Linux用户和用户组
在Azkaban所有机器上创建用户,并将这些用户都加入到一个用户组中,选择其中一个用户启动Azkaban服务。为了举例方便,此处创建了四个用户,并将这些用户加入到user用户组中。
sudo useradd -m user; echo "userxxx" | sudo passwd --stdin data
sudo useradd -m user1; echo "user1xxx" | sudo passwd --stdin data
sudo useradd -m user2; echo "user2xxx" | sudo passwd --stdin data
sudo useradd -m user3; echo "user3xxx" | sudo passwd --stdin data
sudo usermod -G user user1
sudo usermod -G user user2
sudo usermod -G user user3
2. 创建Azkaban用户和用户组
Azkaban中是通过修改Azkaban-user.xml来创建用户和用户组,Azkaban有一个专门的线程来不断监控Azkaban-user.xml并刷新用户信息到内存中。
<azkaban-users>
<!-- user config -->
<user username="azkaban" password="azkaban" groups="azkaban"/>
<user username="metrics" password="metrics" groups="metrics"/>
<user username="user1" password="user1" groups="user"/>
<user username="user2" password="user2" groups="user"/>
<user username="user3" password="user3" groups="user"/>
<!-- group config -->
<group name="admin" roles="admin"/>
<group name="metrics" roles="metrics"/>
<group name="user" roles="ec2-user"/>
<!-- role config -->
<role name="admin" permissions="ADMIN"/>
<role name="metrics" permissions="METRICS"/>
<role name="user" permissions="ADMIN"/>
</azkaban-users>
具体监控azkaban-user.xml是在XMLUserManager类中调用setupWatch函数进行实现
/**
* The mandatory UserManager(Props) constructor, which is called via reflection.
*/
public XmlUserManager(final Props props) {
this(props, FileWatcher::new);
}
XmlUserManager(final Props props, final FileWatcherFactory fileWatcherFactory) {
this.xmlPath = props.getString(XML_FILE_PARAM);
parseXMLFile();
// Create a thread which listens to any change in user config file and
// reloads it.
final Map<String, ParseConfigFile> parseConfigFileMap = new HashMap<>();
parseConfigFileMap.put(this.xmlPath, this::parseXMLFile);
try {
UserUtils.setupWatch(parseConfigFileMap, fileWatcherFactory.get());
} catch (final IOException e) {
logger.warn("Failed to create WatchService", e);
}
}
3. 配置execute-as-user
拷贝Azkaban代码中 azkaban/az-exec-util/src/main/c/execute-as-user.c到Azkaban Executor机器上的Azkaban Executor目录
使用 gcc execute-as-user.c -o execute-as-user 命令编译
然后使用chown root execute-as-user 和 chmod 6050 execute-as-user 设置权限
如果我们要把这个文件复制到其他目录下,就又会变成普通文件,则需要重新再进行一次复制。
---Sr-s--- 1 root root 10185 May 29 06:45 execute-as-user
4. 修改Azkaban源码,禁用user-to-proxy
在Azkaban ProcessJob.java文件中添加一个参数enable.user.to.proxy,并且默认设置为false。当enable.user.to.proxy为false的时候,则不允许Azkaban设置提交作业的user,必须以登录Azkaban Webserver的用户执行flow,具体代码修改如下所示。
private static final String ENABLE_USER_TO_PROXY = "enable.user.to.proxy";
/**
* <pre>
* Determines what user id should the process job run as, in the following order of precedence:
* 1. whether enable USER_TO_PROXY && USER_TO_PROXY
* 2. SUBMIT_USER
* </pre>
*
* @return the user that Azkaban is going to execute as
*/
private String getEffectiveUser(final Props jobProps) {
String effectiveUser = null;
if (this.getSysProps().getBoolean(ENABLE_USER_TO_PROXY, false)
&& jobProps.containsKey(JobProperties.USER_TO_PROXY)) {
effectiveUser = jobProps.getString(JobProperties.USER_TO_PROXY);
} else if (jobProps.containsKey(CommonJobProperties.SUBMIT_USER)) {
effectiveUser = jobProps.getString(CommonJobProperties.SUBMIT_USER);
} else {
throw new RuntimeException(
"Internal Error: No user.to.proxy or submit.user in the jobProps");
}
info("effective user is: " + effectiveUser);
return effectiveUser;
}