aboutsummaryrefslogtreecommitdiff
path: root/bigtop-deploy
diff options
context:
space:
mode:
authorMichael Weiser <m.weiser@science-computing.de>2015-04-28 13:05:35 +0200
committerOlaf Flebbe <of@oflebbe.de>2015-04-28 22:12:13 +0200
commitf460e8f3e66fd28d29bd4e4c0c6b98b39980a012 (patch)
tree8d5abf1701cbf342bbf715318b911e5dcc628e1a /bigtop-deploy
parentb0393b58aa1f4682e25da5ad2d76f35fafe3a969 (diff)
BIGTOP-1670 puppet: Support Kerberos authentication on Hadoop component web GUIs
Support configuration of Kerberos authentication on Hadoop component web GUIs. Also introduce support for trocla for randomly generating secrets that are stored on the master, don't change after creation and can be the same across hosts. Signed-off-by: Olaf Flebbe <of@oflebbe.de>
Diffstat (limited to 'bigtop-deploy')
-rw-r--r--bigtop-deploy/puppet/README.md68
-rw-r--r--bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml14
-rw-r--r--bigtop-deploy/puppet/modules/hadoop/manifests/init.pp74
-rw-r--r--bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml43
-rw-r--r--bigtop-deploy/puppet/modules/kerberos/manifests/init.pp20
5 files changed, 206 insertions, 13 deletions
diff --git a/bigtop-deploy/puppet/README.md b/bigtop-deploy/puppet/README.md
index 18773f81..d3e1a441 100644
--- a/bigtop-deploy/puppet/README.md
+++ b/bigtop-deploy/puppet/README.md
@@ -137,3 +137,71 @@ And run the following on those nodes:
When ignite-hadoop accelerator is deployed the client configs are placed under
/etc/hadoop/ignite.client.conf. All one needs to do to run Mapreduce jobs on ignite-hadoop grid
is to set HADOOP_CONF_DIR=/etc/hadoop/ignite.client.conf in the client session.
+
+# Passwords
+
+These classes are mostly used for regression testing. For ease of use they
+contain insecure default passwords in a number of places. If you intend to use
+them in production environments, make sure to track down all those places and
+set proper passwords. This can be done using the corresponding hiera settings.
+Some of these (but almost certainly not all!) are:
+
+<pre>
+hadoop::common_hdfs::hadoop_http_authentication_signature_secret
+hadoop::httpfs::secret
+</pre>
+
+## Automatic password generation
+
+Instead of explicitly setting passwords in hiera, they can be automatically
+generated using a program called trocla. However, there are a number of caveats
+with this approach at the moment:
+
+* currently this only works for the HTTP and HTTPFS authentication signature
+ secrets.
+* trocla has to be installed beforehand as explained below.
+* Installation from ruby gems needs Internet connectivity and for some
+ dependency gems development packages such as a compiler. This can be avoided
+ by using binary packages from the distribution if available.
+* Puppet has to be used in a master/agent setup. With puppet apply it will not
+ work for the HTTP signature secrets because they needs to be the same across
+ hosts which trocla can only achieve if running on the master.
+* The functionality is disabled by default and needs to be enabled explicitly.
+ Without it, default passwords from the code or hiera are still used.
+
+trocla needs to be installed on the master only. To do so, run the following:
+
+<pre>
+# gem install trocla
+# puppet module install duritong/trocla
+# puppet apply -e "class { 'trocla::config': manage_dependencies => false }"
+</pre>
+
+The trocla ruby gem pulls in highline, moneta and bcrypt. The bcrypt gem needs
+ruby development packages (ruby.h) and a compiler.
+
+Alternatively you can install your distributions' binary packages *before*
+running gem install. On Debian those packages can be installed as follows:
+
+<pre>
+apt-get install ruby-highline ruby-moneta ruby-bcrypt
+</pre>
+
+This installation process is expected to get easier once operation system
+packages have been created. This is actively underway for Debian. See Debian
+bugs #777761 and #777906 for progress.
+
+After installing the trocla gem as outlined above, the following test should
+work:
+
+<pre>
+# puppet apply -e "file { '/tmp/test': content => trocla("test", "plain") }"
+# cat /tmp/test
+puGNOX-G%zYDKHet
+</pre>
+
+Now, automatic password generation can be activated in site.yaml using
+
+<pre>
+hadoop::generate_secrets: true
+</pre>
diff --git a/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml b/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml
index 2751d337..1ea64078 100644
--- a/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml
+++ b/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml
@@ -56,6 +56,20 @@ hadoop::common_hdfs::hadoop_namenode_host: "%{hiera('bigtop::hadoop_head_node')}
# actually default but needed for hadoop_namenode_uri here
hadoop::common_hdfs::hadoop_namenode_port: "8020"
+# Set as shown below in site.yaml to also enable Kerberos authentication
+# on the web GUIs of journalnode, namenode, datanode, resourcemanager and
+# nodemanager when you enable Kerberos for Hadoop API communication. This
+# intentionally is not the default right now.
+#hadoop::common_hdfs::hadoop_http_authentication_type: "%{hiera('hadoop::hadoop_security_authentication')}"
+#
+# A secret is necessary for the cross-service-cross-node session cookie.
+# Provide this by setting the following to something long and secret:
+#hadoop::common_hdfs::hadoop_http_authentication_signature_secret:
+
+# ... or have trocla generate secrets for Hadoop components automatically. For
+# this to work, the trocla puppet module must be installed.
+#hadoop::generate_secrets: true
+
hadoop::common_yarn::hadoop_ps_host: "%{hiera('bigtop::hadoop_head_node')}"
hadoop::common_yarn::hadoop_rm_host: "%{hiera('bigtop::hadoop_head_node')}"
# actually default but needed for hue::server::rm_port here
diff --git a/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp b/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp
index 98e3d2c8..89f15c49 100644
--- a/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp
+++ b/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp
@@ -21,7 +21,9 @@ class hadoop ($hadoop_security_authentication = "simple",
$proxyusers = {
oozie => { groups => 'hudson,testuser,root,hadoop,jenkins,oozie,httpfs,hue,users', hosts => "*" },
hue => { groups => 'hudson,testuser,root,hadoop,jenkins,oozie,httpfs,hue,users', hosts => "*" },
- httpfs => { groups => 'hudson,testuser,root,hadoop,jenkins,oozie,httpfs,hue,users', hosts => "*" } } ) {
+ httpfs => { groups => 'hudson,testuser,root,hadoop,jenkins,oozie,httpfs,hue,users', hosts => "*" } },
+ $generate_secrets = false,
+) {
include stdlib
@@ -155,6 +157,11 @@ class hadoop ($hadoop_security_authentication = "simple",
$hadoop_snappy_codec = undef,
$hadoop_security_authentication = $hadoop::hadoop_security_authentication,
$kerberos_realm = $hadoop::kerberos_realm,
+ $hadoop_http_authentication_type = undef,
+ $hadoop_http_authentication_signature_secret = undef,
+ $hadoop_http_authentication_signature_secret_file = "/etc/hadoop/conf/hadoop-http-authentication-signature-secret",
+ $hadoop_http_authentication_cookie_domain = regsubst($fqdn, "^[^\\.]+\\.", ""),
+ $generate_secrets = $hadoop::generate_secrets,
) inherits hadoop {
$sshfence_keydir = "$hadoop_ha_sshfence_user_home/.ssh"
@@ -229,6 +236,57 @@ class hadoop ($hadoop_security_authentication = "simple",
content => template('hadoop/hdfs-site.xml'),
require => [Package["hadoop"]],
}
+
+ if $hadoop_http_authentication_type == "kerberos" {
+ if $generate_secrets {
+ $http_auth_sig_secret = trocla("hadoop_http_authentication_signature_secret", "plain")
+ } else {
+ $http_auth_sig_secret = $hadoop_http_authentication_signature_secret
+ }
+ if $http_auth_sig_secret == undef {
+ fail("Hadoop HTTP authentication signature secret must be set")
+ }
+
+ file { 'hadoop-http-auth-sig-secret':
+ path => "${hadoop_http_authentication_signature_secret_file}",
+ # it's a password file - do not filebucket
+ backup => false,
+ mode => "0440",
+ owner => "root",
+ # allows access by hdfs and yarn (and mapred - mhmm...)
+ group => "hadoop",
+ content => $http_auth_sig_secret,
+ require => [Package["hadoop"]],
+ }
+
+ # all the services will need this
+ File['hadoop-http-auth-sig-secret'] ~> Service<| title == "hadoop-hdfs-journalnode" |>
+ File['hadoop-http-auth-sig-secret'] ~> Service<| title == "hadoop-hdfs-namenode" |>
+ File['hadoop-http-auth-sig-secret'] ~> Service<| title == "hadoop-hdfs-datanode" |>
+ File['hadoop-http-auth-sig-secret'] ~> Service<| title == "hadoop-yarn-resourcemanager" |>
+ File['hadoop-http-auth-sig-secret'] ~> Service<| title == "hadoop-yarn-nodemanager" |>
+
+ require kerberos::client
+ kerberos::host_keytab { "HTTP":
+ # we need only the HTTP SPNEGO keys
+ princs => [],
+ spnego => true,
+ owner => "root",
+ group => "hadoop",
+ mode => "0440",
+ # we don't actually need this package as long as we don't put the
+ # keytab in a directory managed by it. But it creates group hadoop which
+ # we wan't to give the keytab to.
+ require => Package["hadoop"],
+ }
+
+ # all the services will need this as well
+ Kerberos::Host_keytab["HTTP"] -> Service<| title == "hadoop-hdfs-journalnode" |>
+ Kerberos::Host_keytab["HTTP"] -> Service<| title == "hadoop-hdfs-namenode" |>
+ Kerberos::Host_keytab["HTTP"] -> Service<| title == "hadoop-hdfs-datanode" |>
+ Kerberos::Host_keytab["HTTP"] -> Service<| title == "hadoop-yarn-resourcemanager" |>
+ Kerberos::Host_keytab["HTTP"] -> Service<| title == "hadoop-yarn-nodemanager" |>
+ }
}
class common_mapred_app (
@@ -327,6 +385,7 @@ class hadoop ($hadoop_security_authentication = "simple",
class httpfs ($hadoop_httpfs_port = "14000",
$secret = "hadoop httpfs secret",
+ $generate_secrets = $hadoop::generate_secrets,
$hadoop_core_proxyusers = $hadoop::proxyusers,
$hadoop_security_authentcation = $hadoop::hadoop_security_authentication,
$kerberos_realm = $hadoop::kerberos_realm,
@@ -355,8 +414,19 @@ class hadoop ($hadoop_security_authentication = "simple",
require => [Package["hadoop-httpfs"]],
}
+ if $generate_secrets {
+ $httpfs_signature_secret = trocla("httpfs-signature-secret", "plain")
+ } else {
+ $httpfs_signature_secret = $secret
+ }
+ if $httpfs_signature_secret == undef {
+ fail("HTTPFS signature secret must be set")
+ }
+
file { "/etc/hadoop-httpfs/conf/httpfs-signature.secret":
- content => inline_template("<%= @secret %>"),
+ content => $httpfs_signature_secret,
+ # it's a password file - do not filebucket
+ backup => false,
require => [Package["hadoop-httpfs"]],
}
diff --git a/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml b/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml
index 0b8717b3..f9763626 100644
--- a/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml
+++ b/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml
@@ -93,4 +93,47 @@
</property>
<% end %>
+<% if @hadoop_http_authentication_type == "kerberos" -%>
+ <!-- enable proper authentication instead of static mock authentication as
+ Dr. Who -->
+ <property>
+ <name>hadoop.http.filter.initializers</name>
+ <value>org.apache.hadoop.security.AuthenticationFilterInitializer</value>
+ </property>
+
+ <!-- disable anonymous access -->
+ <property>
+ <name>hadoop.http.authentication.simple.anonymous.allowed</name>
+ <value>false</value>
+ </property>
+
+ <!-- enable kerberos authentication -->
+ <property>
+ <name>hadoop.http.authentication.type</name>
+ <value>kerberos</value>
+ </property>
+
+ <property>
+ <name>hadoop.http.authentication.kerberos.principal</name>
+ <value>HTTP/_HOST@<%= @kerberos_realm %></value>
+ </property>
+
+ <property>
+ <name>hadoop.http.authentication.kerberos.keytab</name>
+ <value>/etc/HTTP.keytab</value>
+ </property>
+
+ <!-- provide secret for cross-service-cross-machine cookie -->
+ <property>
+ <name>hadoop.http.authentication.signature.secret.file</name>
+ <value><%= @hadoop_http_authentication_signature_secret_file %></value>
+ </property>
+
+ <!-- make all services on all hosts use the same cookie domain -->
+ <property>
+ <name>hadoop.http.authentication.cookie.domain</name>
+ <value><%= @hadoop_http_authentication_cookie_domain %></value>
+ </property>
+
+<% end -%>
</configuration>
diff --git a/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp b/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp
index bd5bcca0..4a726a0a 100644
--- a/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp
+++ b/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp
@@ -171,14 +171,11 @@ class kerberos {
}
}
- define host_keytab($princs = undef, $spnego = disabled) {
+ define host_keytab($princs = [ $title ], $spnego = disabled,
+ $owner = $title, $group = "", $mode = "0400",
+ ) {
$keytab = "/etc/$title.keytab"
- $requested_princs = $princs ? {
- undef => [ $title ],
- default => $princs,
- }
-
$internal_princs = $spnego ? {
/(true|enabled)/ => [ 'HTTP' ],
default => [ ],
@@ -186,12 +183,12 @@ class kerberos {
realize(Kerberos::Principal[$internal_princs])
$includes = inline_template("<%=
- [requested_princs, internal_princs].flatten.map { |x|
+ [@princs, @internal_princs].flatten.map { |x|
\"rkt $kerberos::site::keytab_export_dir/#{x}.keytab\"
}.join(\"\n\")
%>")
- kerberos::principal { $requested_princs:
+ kerberos::principal { $princs:
}
exec { "ktinject.$title":
@@ -200,15 +197,16 @@ class kerberos {
$includes
wkt $keytab
EOF
- chown $title $keytab",
+ chown ${owner}:${group} ${keytab}
+ chmod ${mode} ${keytab}",
creates => $keytab,
- require => [ Kerberos::Principal[$requested_princs],
+ require => [ Kerberos::Principal[$princs],
Kerberos::Principal[$internal_princs] ],
}
exec { "aquire $title keytab":
path => $kerberos::site::exec_path,
- user => $title,
+ user => $owner,
command => "bash -c 'kinit -kt $keytab ${title}/$::fqdn ; kinit -R'",
require => Exec["ktinject.$title"],
}