diff --git a/.gitignore b/.gitignore
index 1d88998b07789393e8c45720171bfa9af3cc9eea..7e8eeb4c4f4a996adf3dc219f83c31bbd334d19b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ config.json
 inventory
 hosts
 public_hosts
+secrets.auto.tfvars
 site.pp
 site2.pp
 terraform
diff --git a/deploy.tf b/deploy.tf
index 4cf61ab0fc71175290811d74e242189c2210ad1f..946b044afe17d7518b5ddce5fd612badf56c2499 100644
--- a/deploy.tf
+++ b/deploy.tf
@@ -53,6 +53,11 @@ EOF
 	}
 }
 
+variable "secrets" {
+	type = map(string)
+	# sensitive = true # terraform >= 0.14
+}
+
 output "config" {
 	value = {
 		n = var.n,
@@ -61,6 +66,7 @@ output "config" {
 		master_hostname = var.master_hostname,
 		node_hostname = var.node_hostname,
 		type = var.type,
+		secrets = var.secrets,
 	}
 }
 
diff --git a/deployments/hadoop/ctx.yaml b/deployments/hadoop/ctx.yaml
index f9478250d49c922068f8834f24d6e640615bc756..600ab5438c237f35bc5318fedf6224bb2a30da4a 100644
--- a/deployments/hadoop/ctx.yaml
+++ b/deployments/hadoop/ctx.yaml
@@ -20,6 +20,8 @@ write_files:
       #!/usr/bin/env ruby
       #^syntax detection
       forge "https://forgeapi.puppetlabs.com"
+      mod 'cesnet-kerberos',
+        :git => 'https://github.com/MetaCenterCloudPuppet/cesnet-kerberos/'
       mod 'cesnet-site_hadoop',
         :git => 'https://github.com/MetaCenterCloudPuppet/cesnet-site_hadoop/'
       mod 'cesnet-hadoop',
diff --git a/deployments/hadoop/plugin.py b/deployments/hadoop/plugin.py
index b86c171b755bbcd20e901b2c62af16f73c88181a..3a538923f67cb15e5ab3740f455cd36c2442cbd5 100644
--- a/deployments/hadoop/plugin.py
+++ b/deployments/hadoop/plugin.py
@@ -1,3 +1,4 @@
+import os
 import string
 
 DEFAULT_DISTRIBUTION = 'bigtop'
@@ -16,7 +17,9 @@ class ComponentHadoop:
             'master_hostname': config['master_hostname'],
             'node_hostname': config['node_hostname'],
             'nodes': list([h for h in hosts.keys() if h != config['master_hostname']]),
-            'realm': '',
+            'realm': 'HADOOP',
+            'kerberos_admin_password': config['secrets']['kerberos_admin_password'],
+            'kerberos_master_password': config['secrets']['kerberos_master_password'],
         }
 
     def action(self, action):
@@ -29,11 +32,13 @@ class ComponentHadoop:
                     print('-> site.pp')
                     site = template.substitute(self.params)
                     with open('site.pp', 'w') as f:
+                        os.chmod('site.pp', 0o600)
                         f.write(site)
                     self.params['hdfs_deployed'] = 'true'
                     site = template.substitute(self.params)
                     print('-> site2.pp')
                     with open('site2.pp', 'w') as f:
+                        os.chmod('site2.pp', 0o600)
                         f.write(site)
 
     def commands(self, action):
diff --git a/deployments/hadoop/site.pp.tmpl b/deployments/hadoop/site.pp.tmpl
index cedeff9a6dcec39b3df1ed4e9674e7d3dea6d91c..f739d8833dd1ff22c64be5f192822043999bf71b 100644
--- a/deployments/hadoop/site.pp.tmpl
+++ b/deployments/hadoop/site.pp.tmpl
@@ -34,6 +34,40 @@ $$db_type = "$${operatingsystem}-$${operatingsystemmajrelease}" ? {
   default    => 'mariadb',
 }
 
+$$principals = suffix(concat(
+	prefix(concat([$$master], $$nodes), 'host/'),
+	prefix(concat([$$master], $$nodes), 'HTTP/'),
+	["httpfs/$$master"],
+	prefix(concat([$$master], $$nodes), 'hbase/'),
+	["hive/$$master"],
+	prefix($$nodes, 'dn/'),
+	["jhs/$$master"],
+	["nfs/$$master"],
+	prefix($$nodes, 'nm/'),
+	["nn/$$master"],
+	["oozie/$$master"],
+	["rm/$$master"],
+	["spark/$$master"],
+	["zookeeper/$$master"]
+), "@$${realm}")
+
+stage { 'kerberos':
+  before => Stage['main'],
+}
+
+class{"kerberos":
+  kadmin_hostname    => $$master,
+  admin_principal    => "puppet/admin@$${realm}",
+  admin_password     => '$kerberos_admin_password',
+  master_password    => '$kerberos_master_password',
+  realm              => $$realm,
+  default_attributes => {
+    'requires_preauth' => true,
+  },
+  default_policy     => 'default_host',
+  stage              => 'kerberos',
+}
+
 class{'hadoop':
   acl                    => true,
   hdfs_hostname          => $$master,
@@ -63,7 +97,8 @@ class{'hadoop':
   },
   properties             => {
     'dfs.replication' => 2,
-    'hadoop.proxyuser.hive.groups' => "*",
+    'hadoop.proxyuser.hive.groups' => "hive,impala,oozie,users",
+    #'hadoop.proxyuser.hive.groups' => "*",
     'hadoop.proxyuser.hive.hosts' => "*",
   },
   version                => $$hadoop_version,
@@ -133,6 +168,9 @@ class{'site_hadoop':
     'example',
     'hawking',
   ],
+  user_realms => [
+    '$$realm',
+  ],
   accounting_enable   => false,
   hbase_enable        => true,
   nfs_frontend_enable => false,
@@ -142,12 +180,126 @@ class{'site_hadoop':
 }
 
 # site_hadoop::users hasn't shell on the nodes, we need exception for '${image_user}'
+$$touchfile = 'hdfs-user-${image_user}-created'
 hadoop::user{'${image_user}':
   shell     => true,
   hdfs      => $$hadoop::hdfs_hostname == $$::fqdn,
   groups    => 'users',
   realms    => $$site_hadoop::user_realms,
-  touchfile => 'hdfs-user-${image_user}-created',
+  touchfile => $$touchfile,
+}
+if $$hadoop::hdfs_hostname == $$::fqdn {
+  hadoop::kinit{$$touchfile:
+  }
+  ->
+  Hadoop::User <| touchfile == $$touchfile |>
+  ->
+  hadoop::kdestroy{$$touchfile:
+    touch     => true,
+  }
+}
+
+class local_kerberos {
+  file{'/etc/security/keytab':
+    ensure => 'directory',
+    owner  => 'root',
+    group  => 'root',
+    mode   => '0755',
+  }
+
+  File['/etc/security/keytab'] -> Kerberos::Keytab <| |>
+}
+
+class local_kerberos_master {
+  include local_kerberos
+
+  kerberos::policy{'default':
+    ensure    => 'present',
+    minlength => 6,
+    history   => 2,
+  }
+
+  kerberos::policy{'default_host':
+    ensure    => 'present',
+    minlength => 6,
+  }
+
+  kerberos::principal{$$::kerberos::admin_principal:
+    ensure   => 'present',
+    password => $$::kerberos::admin_password,
+  }
+
+  kerberos::principal{$$principals:}
+
+  kerberos::keytab{'/etc/krb5.keytab':
+    principals => ["host/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/hive.service.keytab':
+    principals => ["hive/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/hbase.service.keytab':
+    principals => ["hbase/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/http.service.keytab':
+    principals => ["HTTP/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/httpfs.service.keytab':
+    principals => ["httpfs/$${::fqdn}@$${realm}"],
+  }
+  # works only locally on Kerberos admin server!
+  kerberos::keytab{'/etc/security/keytab/httpfs-http.service.keytab':
+    principals => [
+      "httpfs/$${::fqdn}@$${realm}",
+      "HTTP/$${::fqdn}@$${realm}",
+    ],
+  }
+  kerberos::keytab{'/etc/security/keytab/jhs.service.keytab':
+    principals => ["jhs/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/nfs.service.keytab':
+    principals => ["nfs/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/nn.service.keytab':
+    principals => ["nn/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/oozie.service.keytab':
+    principals => ["oozie/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/rm.service.keytab':
+    principals => ["rm/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/spark.service.keytab':
+    principals => ["spark/$${::fqdn}@$${realm}"],
+  }
+  kerberos::keytab{'/etc/security/keytab/zookeeper.service.keytab':
+    principals => ["zookeeper/$${::fqdn}@$${realm}"],
+  }
+}
+
+class local_kerberos_node {
+  include local_kerberos
+
+  # this will use kerberos::admin_principal and kerberos::admin_password parameters
+  kerberos::keytab{'/etc/krb5.keytab':
+    principals => ["host/$${::fqdn}@$${realm}"],
+    wait       => 600,
+  }
+  kerberos::keytab{'/etc/security/keytab/dn.service.keytab':
+    principals => ["dn/$${::fqdn}@$${realm}"],
+    wait       => 600,
+  }
+  kerberos::keytab{'/etc/security/keytab/hbase.service.keytab':
+    principals => ["hbase/$${::fqdn}@$${realm}"],
+    wait       => 600,
+  }
+  kerberos::keytab{'/etc/security/keytab/http.service.keytab':
+    principals => ["HTTP/$${::fqdn}@$${realm}"],
+    wait       => 600,
+  }
+  kerberos::keytab{'/etc/security/keytab/nm.service.keytab':
+    principals => ["nm/$${::fqdn}@$${realm}"],
+    wait       => 600,
+  }
 }
 
 node /${master_hostname}\..*/ {
@@ -163,8 +315,16 @@ node /${master_hostname}\..*/ {
     root_password  => 'root',
   }
   #include ::oozie::client
+
+  class{'local_kerberos_master':
+    stage => 'kerberos',
+  }
 }
 
 node /${node_hostname}\d*\..*/ {
   include ::site_hadoop::role::slave
+
+  class{'local_kerberos_node':
+    stage => 'kerberos',
+  }
 }
diff --git a/image/Puppetfile b/image/Puppetfile
index e9ddf2375d11731d8a453f5f4c6c5010c49c6036..2f71a37fee824c096685922491da65a093259dd6 100644
--- a/image/Puppetfile
+++ b/image/Puppetfile
@@ -3,6 +3,9 @@
 
 forge "https://forgeapi.puppetlabs.com"
 
+mod 'cesnet-kerberos',
+  :git => 'https://github.com/MetaCenterCloudPuppet/cesnet-kerberos/'
+
 mod 'cesnet-site_hadoop',
   :git => 'https://github.com/MetaCenterCloudPuppet/cesnet-site_hadoop/'
 
diff --git a/launch.sh b/launch.sh
index 71b6b812cdb32476725e2a2ad1105427e2efdcac..7d63f19869dec63310fb59e653e65c7504e41c89 100755
--- a/launch.sh
+++ b/launch.sh
@@ -1,4 +1,25 @@
 #! /bin/sh -xe
+
+if [ ! -s ./secrets.auto.tfvars ]; then
+	touch ./secrets.auto.tfvars
+	chmod 0600 ./secrets.auto.tfvars
+	{
+		echo 'secrets = {'
+		for k in kerberos_master_password kerberos_admin_password http_signature_secret; do
+			echo "	$k = \"`dd if=/dev/random bs=27 count=1 2>/dev/null | base64 -`\""
+		done
+		echo "}"
+	} >> ./secrets.auto.tfvars
+fi
+
 ./terraform apply -auto-approve "$@"
+
+touch config.json; chmod 0600 config.json
 ./terraform output -json > config.json
-./orchestrate.py
+
+if [ -z "$NO_DEPLOYMENT" ]; then
+	./orchestrate.py
+else
+	./orchestrate.py files ping init wait
+	./orchestrate.py -n deployment
+fi
diff --git a/orchestrate.py b/orchestrate.py
index 06c7d67a123be4f392ae6b9dfa558474dcedd43d..4f83be64e878aa13d6b4c4e02145c27aca1327b4 100755
--- a/orchestrate.py
+++ b/orchestrate.py
@@ -52,6 +52,7 @@ public_hosts = j['public_hosts']['value']
 master_hostname = config['master_hostname']
 master_ip = public_hosts[master_hostname]
 user = config['image_user']
+secrets = config['secrets']
 t = config.get('type', None)
 
 print('== plugin ==')
diff --git a/secrets.auto.tfvars.example b/secrets.auto.tfvars.example
new file mode 100644
index 0000000000000000000000000000000000000000..6a513a791edfa5ecb0fa03d268c504da1ee30ddd
--- /dev/null
+++ b/secrets.auto.tfvars.example
@@ -0,0 +1,5 @@
+secrets = {
+	kerberos_master_password = "SECRET"
+	kerberos_admin_password = "SECRET"
+	http_signature_secret = "SECRET"
+}