背景
默认情况下,运行在 emr
上的 zeppelin
是未开启用户验证的,这意味着集群安全组内的任何人都可以访问 zeppelin
,并在上面运行代码,这无疑是不安全的。我们通过一定的设置为zeppelin
开启用户验证。
手动设置
参考文档 Apache Shiro authentication for Apache Zeppelin,ssh
到已经启动的集群的主节点进行设置。
通过 step
自动设置
手动设置需要在每次集群启动后都设置一遍,如果需要频繁启动集群,就很不方便,因此可以在启动集群的时候使用 step
来自动设置。
具体来说,AWS
提供了一个 script-runner.jar
,它的路径是s3://<YOUR-AWS-REGION>.elasticmapreduce/libs/script-runner/script-runner.jar
,在启动集群的时候,添加这个jar
包作为 step
,指定一个S3
上的 shell
脚本作为参数,就可以在启动集群后马上运行这个脚本了。具体命令如下:
aws emr create-cluster --name "Test cluster" ...(省略部分参数) --steps Type=CUSTOM_JAR,Name=CustomJAR,ActionOnFailure=CONTINUE,Jar=s3://<YOUR-AWS-REGION>.elasticmapreduce/libs/script-runner/script-runner.jar,Args=["s3://mybucket/script-path/add_password.sh mypassword"]
该命令启动一个名为 Test cluster
的集群,并为 zeppelin
的admin
用户加上 mypassword
作为密码。add_password.sh
的代码如下:
#!/bin/bash
password=$1
if test -z "$password"
then
exit 1
fi
aws s3 cp s3://mybucket/script-path/add_password.py /home/hadoop/add_password.py
sudo /usr/bin/python3 /home/hadoop/add_password.py $password
sudo stop zeppelin
sudo start zeppelin
exit 0
可以看到,脚本首先从 s3
上下载一个 python
脚本来完成设置密码的操作,然后再重启 zeppelin
使其生效。对应的 add_password.py
代码如下
#!/usr/bin/python3
import os
import time
import sys
password = str(sys.argv[1]).strip()
with open("/etc/zeppelin/conf/shiro.ini", "r") as f:
lines = f.readlines()
with open("/etc/zeppelin/conf/shiro.ini", "w") as f:
for line in lines:
if line.startswith('admin ='):
f.write('admin = {}\n'.format(password))
elif line.startswith('user'):
continue
elif line.startswith('/** = anon'):
f.write('#/** = anon\n')
elif line.startswith('#/** = authc'):
f.write('/** = authc\n')
else:
f.write(line)
os.popen('cp /etc/zeppelin/conf/zeppelin-site.xml.template /etc/zeppelin/conf/zeppelin-site.xml')
time.sleep(1)
with open("/etc/zeppelin/conf/zeppelin-site.xml", "r") as f:
lines = f.readlines()
with open("/etc/zeppelin/conf/zeppelin-site.xml", "w") as f:
for i, line in enumerate(lines):
if i > 0 and 'zeppelin.anonymous.allowed' in lines[i-1].strip() and line.strip() == '<value>true</value>':
f.write(line.replace('true', 'false'))
else:
f.write(line)
这个 python
脚本写的很简陋,理解就好。