Repository: bigtop
Updated Branches:
  refs/heads/master b0393b58a -> f460e8f3e


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 <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/bigtop/repo
Commit: http://git-wip-us.apache.org/repos/asf/bigtop/commit/f460e8f3
Tree: http://git-wip-us.apache.org/repos/asf/bigtop/tree/f460e8f3
Diff: http://git-wip-us.apache.org/repos/asf/bigtop/diff/f460e8f3

Branch: refs/heads/master
Commit: f460e8f3e66fd28d29bd4e4c0c6b98b39980a012
Parents: b0393b5
Author: Michael Weiser <[email protected]>
Authored: Tue Apr 28 13:05:35 2015 +0200
Committer: Olaf Flebbe <[email protected]>
Committed: Tue Apr 28 22:12:13 2015 +0200

----------------------------------------------------------------------
 bigtop-deploy/puppet/README.md                  | 68 ++++++++++++++++++
 .../puppet/hieradata/bigtop/cluster.yaml        | 14 ++++
 .../puppet/modules/hadoop/manifests/init.pp     | 74 +++++++++++++++++++-
 .../modules/hadoop/templates/core-site.xml      | 43 ++++++++++++
 .../puppet/modules/kerberos/manifests/init.pp   | 20 +++---
 5 files changed, 206 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/bigtop/blob/f460e8f3/bigtop-deploy/puppet/README.md
----------------------------------------------------------------------
diff --git a/bigtop-deploy/puppet/README.md b/bigtop-deploy/puppet/README.md
index 18773f8..d3e1a44 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>

http://git-wip-us.apache.org/repos/asf/bigtop/blob/f460e8f3/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml
----------------------------------------------------------------------
diff --git a/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml 
b/bigtop-deploy/puppet/hieradata/bigtop/cluster.yaml
index 2751d33..1ea6407 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

http://git-wip-us.apache.org/repos/asf/bigtop/blob/f460e8f3/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp
----------------------------------------------------------------------
diff --git a/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp 
b/bigtop-deploy/puppet/modules/hadoop/manifests/init.pp
index 98e3d2c..89f15c4 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"]],
     }
 

http://git-wip-us.apache.org/repos/asf/bigtop/blob/f460e8f3/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml
----------------------------------------------------------------------
diff --git a/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml 
b/bigtop-deploy/puppet/modules/hadoop/templates/core-site.xml
index 0b8717b..f976362 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>

http://git-wip-us.apache.org/repos/asf/bigtop/blob/f460e8f3/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp
----------------------------------------------------------------------
diff --git a/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp 
b/bigtop-deploy/puppet/modules/kerberos/manifests/init.pp
index bd5bcca..4a726a0 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"],
     }

Reply via email to