This is the first tutorial in a planned three part series on securing Apache
Storm. In this post we will look at setting up a simple Storm cluster that authenticates users via Kerberos, and how to run a simple topology on it. Future posts will cover authorization using Apache
Ranger. For more information on how to setup Kerberos for Apache Storm, please see the following
documentation.
1) Set up a KDC using Apache Kerby
As for other kerberos-related tutorials that I have written on this blog, we will use a github project I wrote that uses Apache Kerby to start up a KDC:
- bigdata-kerberos-deployment: This project contains some tests which can be used to test kerberos with
various big data deployments, such as Apache Hadoop etc.
The KDC is a simple junit test that is available
here.
To run it just comment out the "org.junit.Ignore" annotation on the
test method. It uses Apache Kerby to define the following principals:
- zookeeper/localhost@storm.apache.org
- zookeeper-client@storm.apache.org
- storm/localhost@storm.apache.org
- storm-client@storm.apache.org
- alice@storm.apache.org
Keytabs are created in the "target" folder. Kerby is configured to use a random port to lauch
the KDC each time, and it will create a "krb5.conf" file containing the
random port number in the target directory.
2) Download and configure Apache Zookeeper
Apache Storm uses Apache
Zookeeper to help coordinate the cluster. Download Apache Zookeeper (this tutorial used 3.4.10) and extract it to a local directory. Configure Zookeeper to use Kerberos by adding a new file 'conf/zoo.cfg' with the following properties:
- dataDir=/tmp/zookeeper
- clientPort=2181
- authProvider.1 = org.apache.zookeeper.server.auth.SASLAuthenticationProvider
- requireClientAuthScheme=sasl
- jaasLoginRenew=3600000
Now create 'conf/zookeeper.jaas' with the following content:
Server {
com.sun.security.auth.module.Krb5LoginModule required
refreshKrb5Config=true useKeyTab=true
keyTab="/path.to.kerby.project/target/zookeeper.keytab" storeKey=true
principal="zookeeper/localhost";
};
Before launching Zookeeper, we need to point to the JAAS configuration
file above and also to the krb5.conf file generated in the Kerby
test-case above. Add a new file 'conf/java.env' adding the SERVER_JVMFLAGS property to the classpath with:
- -Djava.security.auth.login.config=/path.to.zookeeper/conf/zookeeper.jaas
- -Djava.security.krb5.conf=/path.to.kerby.project/target/krb5.conf".
Start Zookeeper via:
3) Download and configure Apache Storm
Now download and extract the Apache Storm distribution (1.1.0 was used in this tutorial). Edit 'conf/storm.yaml' and edit the following properties:
- For "storm.zookeeper.servers" add "- localhost"
- nimbus.seeds: ["localhost"]
- storm.thrift.transport: "org.apache.storm.security.auth.kerberos.KerberosSaslTransportPlugin"
- java.security.auth.login.config: "/path.to.storm/conf/storm.jaas"
- storm.zookeeper.superACL: "sasl:storm"
- nimbus.childopts: "-Djava.security.auth.login.config=/path.to.storm/conf/storm.jaas -Djava.security.krb5.conf=/path.to.kerby.project/target/krb5.conf"
- ui.childopts: "-Djava.security.auth.login.config=/path.to.storm/conf/storm.jaas -Djava.security.krb5.conf=/path.to.kerby.project/target/krb5.conf"
- supervisor.childopts: "-Djava.security.auth.login.config=/path.to.storm/conf/storm.jaas -Djava.security.krb5.conf=/path.to.kerby.project/target/krb5.conf"
Create a file called 'conf/storm.jaas' with the content:
Client {
com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useKeyTab=true keyTab="/path.to.kerby.project/target/zookeeper_client.keytab" storeKey=true principal="zookeeper-client";
};
StormClient {
com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useKeyTab=true keyTab="path.to.kerby.project/target/storm_client.keytab" storeKey=true principal="storm-client" serviceName="storm";
};
StormServer {
com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useKeyTab=true keyTab="path.to.kerby.project/target/storm.keytab" storeKey=true principal="storm/localhost@storm.apache.org";
};
'Client' is used to communicate with Zookeeper, 'StormClient' is used by the supervisor nodes and 'StormServer' is used by nimbus. Now start Nimbus and a supervisor node via:
- bin/storm nimbus
- bin/storm supervisor
4) Deploy a Topology
As we have the Storm cluster up and running, the next task is to deploy a Topology to it. For this we will need to use another Storm distribution, so extract Storm again to another directory. Edit 'conf/storm.yaml' and edit the following properties:
- For "storm.zookeeper.servers" add "- localhost"
- nimbus.seeds: ["localhost"]
- storm.thrift.transport: "org.apache.storm.security.auth.kerberos.KerberosSaslTransportPlugin"
- java.security.auth.login.config: "/path.to.storm.client/conf/storm.jaas"
Create a file called 'conf/storm.jaas' with the content:
StormClient {
com.sun.security.auth.module.Krb5LoginModule required refreshKrb5Config=true useTicketCache=true serviceName="storm";
};
Note that we are not using keytabs here, but instead a ticket cache. Now edit 'conf/storm_env.ini' and add:
- STORM_JAR_JVM_OPTS:-Djava.security.krb5.conf=/path.to.kerby.project/target/krb5.conf
Now that we have everything set up, it's time to deploy a topology to our cluster. I have a simple Storm topology
that wires a WordSpout + WordCounterBolt into a topology that can be used for this in github
here. Check this project out from github + build it via "mvn assembly:assembly". We will need a Kerberos ticket store in our ticket cache to deploy the job:
- export KRB5_CONFIG=/path.to.kerby.project/target/krb5.conf
- kinit -k -t /path.to.kerby.project/target/alice.keytab alice
Finally we can submit our topology:
- bin/storm jar /path.to.storm.project/target/bigdata-storm-demo-1.0-jar-with-dependencies.jar org.apache.coheigea.bigdata.storm.StormMain /path.to.storm.project/target/test-classes/words.txt
If you take a look at the logs in the nimbus distribution you should see that the topology has run correctly, e.g. 'logs/workers-artifacts/mytopology-1-1495813912/6700/worker.log'.