AWS实战 - EMR Zeppelin启用用户验证


背景

默认情况下,运行在emr上的zeppelin是未开启用户验证的,这意味着集群安全组内的任何人都可以访问zeppelin,并在上面运行代码,这无疑是不安全的。我们通过一定的设置为zeppelin开启用户验证。

手动设置

参考文档Apache Shiro authentication for Apache Zeppelinssh到已经启动的集群的主节点进行设置。

通过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的集群,并为zeppelinadmin用户加上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脚本写的很简陋,理解就好。