One environment variable, and the folder was gone
The canteen cluster now holds payroll files for the staff. Riya, testing permissions, is correctly refused: Permission denied: user=riya. Then Kabir types one extra word before the same command, HADOOP_USER_NAME=hadoop, and the folder is listed, and then deleted. Nobody hacked anything. On a cluster without Kerberos, Hadoop simply believes whatever user name the client says it is.
Sir, so the permissions are fake?
The permissions are real; the identity is not. HDFS checks riya against the folder correctly. It just has no way to know you really are Riya. That is authentication, and in Hadoop it is done by Kerberos.
And once we know who someone is, who decides what they may read in every table and folder, across HDFS and Hive?
That is authorization: HDFS permissions and ACLs at the simplest level, and Apache Ranger for central policies with audit. Today we build a real Kerberos KDC and a secured NameNode, try to cheat it, read the KDC's log, and add an ACL. Ranger we study on paper, because our laptop lab did not run it.
Hadoop security: Kerberos and Ranger
Hadoop security rests on four pillars: authentication (proving identity), authorization (deciding what an identity may do), audit (recording who did what) and data protection (encryption on the wire and at rest). By default Hadoop uses simple authentication, in which the client's claimed user name is trusted. In secure mode (hadoop.security.authentication=kerberos) every user and service proves its identity to a Kerberos Key Distribution Center (KDC): a principal obtains a ticket-granting ticket (TGT) from the Authentication Service with a password or a keytab, then obtains service tickets from the Ticket-Granting Service for each Hadoop service, such as nn/host@REALM; jobs then use Hadoop delegation tokens. Apache Ranger provides centralized, fine-grained authorization: administrators define resource-based or tag-based policies in Ranger Admin, plugins inside services such as the NameNode, HiveServer2, HBase and YARN enforce them locally, and every access decision is written to an audit store.
Kerberos is the ID card: no card, no entry, and you cannot borrow someone else's name. Ranger is the rule book and the CCTV: one place says who may open which door, every building follows it, and every opening is recorded.
Words you'll meet in this lesson
riya@LAB.MYPHATSHALA or nn/nn-secure@LAB.MYPHATSHALA.nn/nn-secure.From our lab (Hadoop 3.5.0, MIT Kerberos from Ubuntu 24.04)
| Unsecured | riya: Permission denied … inode="/secure_demo":hadoop:supergroup:drwx------; with HADOOP_USER_NAME=hadoop: listed, then Deleted /secure_demo |
|---|---|
| Secured, no ticket | AccessControlException · Client cannot authenticate via:[TOKEN, KERBEROS]; HADOOP_USER_NAME=nn gives the same |
| Secured, riya's ticket | klist: TGT krbtgt/LAB.MYPHATSHALA for 10 hours; her file is owned by riya; /payroll denied, also when she claims to be nn |
| KDC log | 1 AS_REQ riya@… for krbtgt/…, then 4 TGS_REQ riya@… for nn/nn-secure@…; wrong password: kinit: Password incorrect |
| HDFS ACL | user:kabir:r-x on /finance: kabir sees 1 file, riya is denied; ls -d shows drwxr-x---+ |
| Not run | Apache Ranger, secure DataNodes, KMS encryption zones: explained here, not installed in our lab |
Architecture at a glance
A secured cluster as most companies run it. Green borders are what our lab really ran; dashed grey boxes are explained but were not installed.
Security at three levels
Beginner The office building
- Authentication is the ID card at the gate. Without Kerberos, the guard asks “what's your name?” and believes the answer: that is what
HADOOP_USER_NAMEexploited. - Authorization is which rooms your card opens: HDFS permissions, ACLs and Ranger policies.
- Audit is the visitor register and CCTV. Encryption is locking the files themselves, so a stolen disk is useless.
Intermediate How a Kerberos login works in Hadoop
kinit riyasends an AS_REQ; the KDC returns a TGT encrypted with a key derived from riya's password. Only the right password can open it, so the password never crosses the network. A wrong one gives Password incorrect.- The first
hdfs dfscommand uses the TGT to send a TGS_REQ fornn/nn-secure. Our KDC log shows 4 of them for riya's commands; Java keeps those service tickets in memory, which is whyklistshowed only the TGT. - The NameNode decrypts the ticket with its own key from the keytab, learns “this is riya@LAB.MYPHATSHALA”, maps it to the short name riya (auth_to_local) and then checks permissions as before.
- A MapReduce or Spark job obtains delegation tokens at submission and ships them to its containers, so thousands of tasks don't each hit the KDC.
Advanced Running it in production
- Every daemon gets its own principal and keytab (
nn/host,dn/host,rm/host,nm/host,HTTP/hostfor SPNEGO web UIs); keytabs are root-only files. - Secure DataNodes need privileged ports or SASL data-transfer protection with HTTPS; that is why our secure lab ran only a NameNode and created empty files.
- Kerberos needs DNS (forward and reverse) and clocks within 5 minutes of each other; most “GSS initiate failed” incidents are clock skew, DNS or an expired keytab (wrong KVNO).
- Companies usually use Active Directory as the KDC, run Ranger for policies and audit, encrypt RPC (
hadoop.rpc.protection=privacy) and data transfer, and use HDFS encryption zones with a KMS for sensitive data. Apache Knox can give a single HTTPS entry point.
Exam tip: For “Explain Kerberos authentication in Hadoop”, give the three exchanges (AS: TGT; TGS: service ticket; client to service: ticket), name the keytab and the principal format service/host@REALM, and say why simple authentication is unsafe (the client's user name is trusted).
The layers of Hadoop security
| Layer | Question | Hadoop tool | In our lab? |
|---|---|---|---|
| Authentication | Who are you, really? | Kerberos (MIT or Active Directory), delegation tokens | Yes: KDC + secured NameNode |
| Authorization (basic) | May this user touch this file? | HDFS permissions, POSIX-style ACLs, YARN queue ACLs | Yes: ACL on /finance |
| Authorization (central) | One policy for HDFS, Hive, HBase, Kafka… | Apache Ranger (resource and tag policies, masking, row filters) | No (concepts) |
| Audit | Who did what, when, allowed or denied? | Ranger audit, HDFS audit log (hdfs-audit.log) | KDC log only |
| Encryption in transit | Can someone sniff the network? | RPC privacy, data transfer protection, TLS for web UIs | No |
| Encryption at rest | Is a stolen disk readable? | HDFS transparent encryption zones + Hadoop KMS | No |
| Perimeter | One safe door from outside | Apache Knox gateway, edge nodes | No |
HDFS ACL or Ranger policy?
HDFS permissions + ACLs
Stored on each file or folder in the NameNode. Good for a few exceptions (“kabir may also read /finance”). Spread across thousands of paths, hard to review, HDFS only.
built inRanger resource policy
“Group finance-analysts: read on /finance/*, select on db finance”. Defined once in Ranger Admin, cached by plugins, audited centrally, works across HDFS, Hive, HBase, Kafka.
centralRanger tag policy
Columns tagged PII in Apache Atlas are masked for everyone except approved groups, wherever the data is copied.
by classificationRanger masking / row filter
Hive shows XXXX-XXXX-1234 instead of a card number, or only the rows of the analyst's own state.
Animated example: an intern and the salary table
A bank with Kerberos, Ranger and audit in place. The story is illustrative; the messages in the first two steps are the ones our lab printed.
- Pretending: the intern claims to be hr_admin. On a Kerberos cluster that is ignored: no ticket, no connection.
- Logging in: with
kinitshe proves who she really is and gets a TGT. - Asking: she queries the salary table; HiveServer2 knows exactly who is asking.
- Ranger decides: no policy lets the interns group read hr tables, so the plugin denies it.
- Audit: the denial is recorded with user, resource, time and client address for the security team.
- The fix: instead of more exceptions, a masking policy gives interns the table with the salary column hidden.
Pick the lightest tool that works: owner/group permissions for most paths, an ACL for a rare exception, and Ranger once you have many users, several services, or auditors asking “who could read this column last March?”.
From “anyone can be hadoop” to tickets and ACLs
Part 1 runs on the Module 8 lab. Part 2 uses three new containers (kerberos/docker-compose.yaml in “Run it on your PC”): an Ubuntu KDC, a Kerberos-secured NameNode and a client.
Unsecured: claim to be the owner
WithHADOOP_USER_NAME=riya hdfs dfs -cat /secure_demo/salaries.csv HADOOP_USER_NAME=hadoop hdfs dfs -rm -r -skipTrash /secure_demoPermission denied: user=riya, access=EXECUTE, inode="/secure_demo":hadoop:supergroup:drwx------ Deleted /secure_demohadoop.security.authentication=simplethe client simply sends a user name, taken from the OS or fromHADOOP_USER_NAME. HDFS checks permissions against that name faithfully, which protects against mistakes, never against intent.Build a KDC and secure the NameNode
Our first start failed for real: the image formats the NameNode when the container starts, before the KDC had written the keytab, giving KerberosAuthException: failure to login … Unable to obtain password from user. The fix was to wait untilkdb5_util create -s -r LAB.MYPHATSHALA kadmin.local -q "addprinc -randkey nn/nn-secure@LAB.MYPHATSHALA" kadmin.local -q "addprinc -pw riya123 riya@LAB.MYPHATSHALA" kadmin.local -q "ktadd -k /keytabs/nn.keytab nn/nn-secure@LAB.MYPHATSHALA HTTP/nn-secure@LAB.MYPHATSHALA" CORE-SITE.XML_hadoop.security.authentication=kerberos HDFS-SITE.XML_dfs.namenode.kerberos.principal=nn/nn-secure@LAB.MYPHATSHALA HDFS-SITE.XML_dfs.namenode.keytab.file=/keytabs/nn.keytabINFO UserGroupInformation - Login successful for user nn/nn-secure@LAB.MYPHATSHALA using keytab file nn.keytab INFO Server - IPC Server listener on 8020: startingkinit -ktworks, then format and start.No ticket, no entry
The client offered neither a Kerberos ticket nor a delegation token, so the NameNode refused the connection before any file was checked. The environment variable is ignored in secure mode.hdfs dfs -ls / HADOOP_USER_NAME=nn hdfs dfs -ls /AccessControlException Client cannot authenticate via:[TOKEN, KERBEROS] Client cannot authenticate via:[TOKEN, KERBEROS]Log in as riya and look at the ticket
The TGT lasts 10 hours (kinit riya@LAB.MYPHATSHALA klist hdfs dfs -touchz /user/riya/notes.txt hdfs dfs -ls /user/riyaDefault principal: riya@LAB.MYPHATSHALA Valid starting Expires Service principal 10/22/2026 10:08:23 10/22/2026 20:08:23 krbtgt/LAB.MYPHATSHALA@LAB.MYPHATSHALA -rw-r--r-- riya /user/riya/notes.txtticket_lifetime = 10hin krb5.conf). Hadoop's Java client then asks the KDC for a service ticket fornn/nn-secureand keeps it in memory. We usedtouchzbecause the secure lab has no DataNode: secure DataNodes need privileged ports or SASL with HTTPS.Try the payroll folder, and try to pretend
Now the user name comes from the ticket, so both attempts are riya. Note the owner of /payroll is nn: the short name ofhdfs dfs -cat /payroll/salaries.csv HADOOP_USER_NAME=nn hdfs dfs -cat /payroll/salaries.csv kdestroy; kinit riya@LAB.MYPHATSHALA # with a wrong passwordPermission denied: user=riya, access=EXECUTE, inode="/payroll":nn:supergroup:drwx------ Permission denied: user=riya, access=EXECUTE, inode="/payroll":nn:supergroup:drwx------ kinit: Password incorrect while getting initial credentialsnn/nn-secure@LAB.MYPHATSHALAafter the default auth_to_local rule.Read the KDC's log
Exactly the two exchanges from the definition: one AS request for a TGT, then TGS requests for the NameNode's service ticket (one perdocker logs lab12k-kdc-1 | grep -E "AS_REQ|TGS_REQ"1 AS_REQ 172.23.0.3: ISSUE: riya@LAB.MYPHATSHALA for krbtgt/LAB.MYPHATSHALA@LAB.MYPHATSHALA 4 TGS_REQ 172.23.0.3: ISSUE: riya@LAB.MYPHATSHALA for nn/nn-secure@LAB.MYPHATSHALA 1 AS_REQ 172.23.0.3: ISSUE: nn/nn-secure@LAB.MYPHATSHALA for krbtgt/LAB.MYPHATSHALA@LAB.MYPHATSHALA 4 TGS_REQ 172.23.0.3: ISSUE: nn/nn-secure@LAB.MYPHATSHALA for nn/nn-secure@LAB.MYPHATSHALAhdfscommand, since each is a new JVM). The KDC never sees a password; it only encrypts with the key derived from it.Authorization beyond owner and group: an ACL
Thehdfs dfs -chmod 750 /finance hdfs dfs -setfacl -m user:kabir:r-x /finance hdfs dfs -getfacl /financeuser::rwx user:kabir:r-x group::r-x mask::r-x other::--- -- kabir (named in the ACL): 1 file visible -- riya (not in the ACL): Permission denied: user=riya drwxr-x---+ hadoop /finance+after the permission bits means “has an ACL”. Ranger generalises this idea: policies by user or group, kept in one place, across services, with audit. (This step ran on the unsecured lab, so the names are only as trustworthy as step 1.)
Keytabs are as powerful as passwords that never expire. Keep them readable only by the service user, never in Git, and rotate them; a copied keytab lets anyone become that service.
A Kerberos login, as the KDC saw it
Six steps from our secure lab: the client's terminal on the left, the KDC and NameNode on the right.
- Without a ticket the very first command is refused.
- Claiming to be the NameNode's user changes nothing.
- riya logs in with her password; klist shows her TGT, valid for 10 hours.
- Now commands work, and the file she creates is owned by riya.
- She tries to pretend again to read payroll: still riya, still denied.
- A wrong password never gets a usable ticket.
- The NameNode's RPC layer demands Kerberos or a delegation token during the connection handshake.
- The user name variable is simply not used in secure mode; identity comes only from credentials.
- kinit sends an AS request; the KDC returns a TGT that only riya's password can unlock.
- For each command the client asks the TGS for an nn/nn-secure ticket; the NameNode reads riya from it.
- Authentication done, the usual HDFS permission check denies riya on /payroll.
- With a wrong password the client cannot decrypt the KDC's reply, so it never gets a TGT.
Security at work
1. Banking: masking card numbers
Analysts query transaction tables in Hive; a Ranger masking policy shows only the last four digits of card numbers to everyone outside the fraud team, and every query is audited.
2. Hospitals: tag-based policies on patient data
Columns such as patient name and diagnosis are tagged PII in Atlas; one Ranger tag policy protects them in every table and copy, so researchers get de-identified data.
3. Telecom: one login for thousands of employees
The corporate Active Directory acts as the KDC; employees' Windows logins give them Kerberos tickets, and leaving the company disables cluster access the same day.
4. Government schemes: encryption zones for beneficiary data
Folders holding beneficiary records are HDFS encryption zones; files are encrypted with keys held by the KMS, so a disk taken out for repair reveals nothing.
5. E-commerce: audit trails for compliance reviews
Ranger audit records who read customer address tables; a monthly report flags unusual access, for example a service account suddenly reading data it never read before.
Simplified; organisations differ in tools and policies. India's Digital Personal Data Protection Act, 2023 adds legal duties for personal data; ask your legal team what applies, this lesson is not legal advice.
Simulate a Kerberos login
A toy Kerberos with real ideas and fake cryptography: each principal has a secret key, tickets are “sealed” with the key of whoever must read them, and every ticket has an expiry time. Watch how riya gets into the NameNode and why an impostor cannot.
import hashlib
def key(secret): # a "key" derived from a password or keytab
return hashlib.sha256(secret.encode()).hexdigest()[:8]
def seal(k, data): return {"sealed_with": k, "data": data}
def open_(k, box):
if box["sealed_with"] != k:
raise PermissionError("cannot decrypt: wrong key")
return box["data"]
KDC = {"riya@LAB": key("riya123"), "krbtgt@LAB": key("kdc-secret"), "nn/nn-secure@LAB": key("from-keytab")}
def as_req(user, now): # 1. AS: password -> TGT
tgt = seal(KDC["krbtgt@LAB"], {"user": user, "expires": now + 10})
return seal(KDC[user], {"tgt": tgt}) # only the user's key opens the reply
def tgs_req(tgt, service, now): # 2. TGS: TGT -> service ticket
t = open_(KDC["krbtgt@LAB"], tgt)
if now > t["expires"]:
raise PermissionError("TGT expired")
return seal(KDC[service], {"user": t["user"], "expires": t["expires"]})
def namenode(ticket, claimed_name=None): # 3. service: reads the user from the ticket
t = open_(KDC["nn/nn-secure@LAB"], ticket)
return f"NameNode sees user={t['user'].split('@')[0]} (claimed {claimed_name})"
reply = as_req("riya@LAB", now=0)
tgt = open_(key("riya123"), reply)["tgt"] # riya types the right password
ticket = tgs_req(tgt, "nn/nn-secure@LAB", now=1)
print(namenode(ticket, claimed_name="nn"))
try:
open_(key("wrongpass"), reply)
except PermissionError as e:
print("wrong password:", e)return seal(KDC[user], {"tgt": tgt}) # only the user's key opens the replyThe KDC answers anyone, but the answer is sealed with the user's key. That is why a wrong password gave "Password incorrect" without the password crossing the network.return seal(KDC[service], {"user": t["user"], "expires": t["expires"]})A service ticket is sealed with the service's key, which the NameNode has in its keytab.t = open_(KDC["nn/nn-secure@LAB"], ticket)The NameNode takes the user from the ticket. The claimed name is ignored, as HADOOP_USER_NAME was in our lab.
Run it on your PC: a KDC, a secured NameNode and an ACL
Part 1 and Part 3 use the Module 8 lab. Part 2 needs the three containers in the kerberos folder: an Ubuntu KDC (it installs MIT Kerberos with apt the first time, so it needs internet), a NameNode with Kerberos switched on, and a client. Put the five files below in a folder called kerberos, with an empty keytabs subfolder, then run docker compose -p lab12k up -d, wait about two minutes and run bash kerberos_lab.sh. Our secure NameNode has no DataNodes, so the demo only creates empty files.
The three containers
# Lab 12.5: a Kerberos KDC, a Kerberos-secured NameNode, and a client machine.
services:
kdc:
image: ubuntu:24.04
hostname: kdc
command: ["bash", "/lab/kdc.sh"]
volumes: [./:/lab:ro, ./keytabs:/keytabs]
nn-secure:
image: apache/hadoop:3.5.0
hostname: nn-secure
command: ["bash", "-c", "until kinit -kt /keytabs/nn.keytab nn/nn-secure@LAB.MYPHATSHALA 2>/dev/null; do sleep 3; done; kdestroy; [ -d /tmp/hadoop-hadoop/dfs/name/current ] || hdfs namenode -format -force -nonInteractive; hdfs namenode"]
env_file: [./config]
# no ENSURE_NAMENODE_DIR: the image would format before the keytab exists; we format after the KDC is up
environment: { KRB5_CONFIG: /lab/krb5.conf }
volumes: [./:/lab:ro, ./keytabs:/keytabs:ro, ./krb5.conf:/etc/krb5.conf:ro]
depends_on: [kdc]
client:
image: apache/hadoop:3.5.0
hostname: client
command: ["sleep", "infinity"]
env_file: [./config]
volumes: [./krb5.conf:/etc/krb5.conf:ro, ./keytabs:/keytabs:ro]
# ---- krb5.conf (same folder) ----
# [libdefaults]
# default_realm = LAB.MYPHATSHALA
# dns_lookup_realm = false
# dns_lookup_kdc = false
# udp_preference_limit = 1
# ticket_lifetime = 10h
# forwardable = true
# [realms]
# LAB.MYPHATSHALA = {
# kdc = kdc
# admin_server = kdc
# }
# ---- config (same folder) ----
# CORE-SITE.XML_fs.defaultFS=hdfs://nn-secure:8020
# CORE-SITE.XML_hadoop.security.authentication=kerberos
# CORE-SITE.XML_hadoop.security.authorization=true
# HDFS-SITE.XML_dfs.namenode.rpc-address=nn-secure:8020
# HDFS-SITE.XML_dfs.namenode.kerberos.principal=nn/nn-secure@LAB.MYPHATSHALA
# HDFS-SITE.XML_dfs.namenode.keytab.file=/keytabs/nn.keytab
# HDFS-SITE.XML_dfs.web.authentication.kerberos.principal=HTTP/nn-secure@LAB.MYPHATSHALA
# HDFS-SITE.XML_dfs.web.authentication.kerberos.keytab=/keytabs/nn.keytab
# HDFS-SITE.XML_dfs.block.access.token.enable=true
# HDFS-SITE.XML_dfs.replication=1Real lines (timestamps removed). The NameNode command waits until kinit with the keytab works, then formats and starts. Our first version let the image format at container start, before the keytab existed, and failed with "KerberosAuthException: failure to login … Unable to obtain password from user".
The KDC: realm, principals, keytab
# kdc.sh: a tiny MIT Kerberos KDC for the lab: realm LAB.MYPHATSHALA
set -e
apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq krb5-kdc krb5-admin-server > /dev/null
cp /lab/krb5.conf /etc/krb5.conf
mkdir -p /etc/krb5kdc /var/lib/krb5kdc
printf '[logging]\n kdc = STDERR\n[realms]\n LAB.MYPHATSHALA = {\n database_name = /var/lib/krb5kdc/principal\n acl_file = /etc/krb5kdc/kadm5.acl\n key_stash_file = /etc/krb5kdc/stash\n }\n' > /etc/krb5kdc/kdc.conf
echo '*/admin@LAB.MYPHATSHALA *' > /etc/krb5kdc/kadm5.acl
kdb5_util create -s -r LAB.MYPHATSHALA -P masterkey123 > /dev/null
kadmin.local -q "addprinc -randkey nn/nn-secure@LAB.MYPHATSHALA" > /dev/null # the NameNode service
kadmin.local -q "addprinc -randkey HTTP/nn-secure@LAB.MYPHATSHALA" > /dev/null # its web UI (SPNEGO)
kadmin.local -q "addprinc -pw riya123 riya@LAB.MYPHATSHALA" > /dev/null # two people
kadmin.local -q "addprinc -pw kabir123 kabir@LAB.MYPHATSHALA" > /dev/null
rm -f /keytabs/nn.keytab
kadmin.local -q "ktadd -k /keytabs/nn.keytab nn/nn-secure@LAB.MYPHATSHALA HTTP/nn-secure@LAB.MYPHATSHALA" > /dev/null
chmod 644 /keytabs/nn.keytab
kadmin.local -q "listprincs"
echo "KDC ready"
exec krb5kdc -nReal output of docker logs lab12k-kdc-1. krbtgt is the KDC's own principal (it seals every TGT); K/M is the master key.
Unsecured vs Kerberos vs ACL
# kerberos_lab.sh: the same commands on an unsecured cluster and on a Kerberos-secured NameNode.
# Run on your PC: part 1 uses the Module 8 lab, part 2 the lab12k containers.
echo "######## 1. UNSECURED (Module 8 lab): Hadoop believes whatever user name you claim"
docker exec lab8-namenode-1 bash -c '
hdfs dfs -mkdir -p /secure_demo && hdfs dfs -chmod 700 /secure_demo && hdfs dfs -put -f /etc/hostname /secure_demo/salaries.csv
echo "-- as riya (not the owner):"
HADOOP_USER_NAME=riya hdfs dfs -cat /secure_demo/salaries.csv 2>&1 | grep -o "Permission denied.*" | cut -c1-120
echo "-- as riya, claiming to be the owner \"hadoop\":"
HADOOP_USER_NAME=hadoop hdfs dfs -ls /secure_demo 2>&1 | grep salaries | awk "{print \$1, \$3, \$8}"
echo "-- as anyone, claiming to be the owner, deleting it:"
HADOOP_USER_NAME=hadoop hdfs dfs -rm -r -skipTrash /secure_demo 2>&1 | grep -v INFO'
echo
echo "######## 2. KERBEROS (lab12k): identity comes from a ticket, not from a variable"
docker exec lab12k-client-1 bash -c 'quiet() { grep -vE "^\s|^Usage|^$|^Generic|^command|^-[a-z]+ <|WARN"; }
echo "-- no ticket:"
hdfs dfs -ls / 2>&1 | grep -oE "Client cannot authenticate via:\[[A-Z, ]+\]|AccessControlException|GSS initiate failed" | sort -u | head -2
echo "-- claiming a name does nothing now:"
HADOOP_USER_NAME=nn hdfs dfs -ls / 2>&1 | grep -oE "Client cannot authenticate via:\[[A-Z, ]+\]" | head -1
echo "-- the service admin logs in with its keytab and makes a home folder for riya:"
kinit -kt /keytabs/nn.keytab nn/nn-secure@LAB.MYPHATSHALA
hdfs dfs -mkdir -p /user/riya /payroll 2>&1 | quiet
hdfs dfs -chown riya /user/riya; hdfs dfs -chmod 700 /payroll
hdfs dfs -touchz /payroll/salaries.csv # our secure lab has no DataNode, so we create empty files (metadata only)
kdestroy
echo "-- riya logs in with her password:"
echo riya123 | kinit riya@LAB.MYPHATSHALA > /dev/null
klist | sed -n "1,6p"
hdfs dfs -touchz /user/riya/notes.txt
hdfs dfs -ls /user/riya | grep notes | awk "{print \$1, \$3, \$8}"
echo "-- riya tries the payroll folder, and tries to pretend:"
hdfs dfs -cat /payroll/salaries.csv 2>&1 | grep -o "Permission denied.*" | cut -c1-110
HADOOP_USER_NAME=nn hdfs dfs -cat /payroll/salaries.csv 2>&1 | grep -o "Permission denied.*" | cut -c1-110
echo "-- the cache holds only the TGT; Java asks the KDC for the NameNode service ticket in memory"
klist | grep -E "krbtgt|nn/"
echo "-- wrong password:"
kdestroy; echo wrongpass | kinit riya@LAB.MYPHATSHALA 2>&1 | tail -1'
echo "-- the KDC log saw all of it:"
docker logs lab12k-kdc-1 2>&1 | grep -E "AS_REQ|TGS_REQ" | sed -E 's/^.*krb5kdc\[[0-9]+\]\(info\): //; s/ \([0-9]+ etypes \{[^}]*\}\)//; s/authtime [0-9]+, etypes \{[^}]*\}, //' | uniq -c | tail -8
echo
echo "######## 3. AUTHORIZATION beyond owner/group: an HDFS ACL (Module 8 lab; the idea Ranger extends)"
docker exec lab8-namenode-1 bash -c '
hdfs dfs -mkdir -p /finance && hdfs dfs -chmod 750 /finance && hdfs dfs -touchz /finance/q3.csv
hdfs dfs -setfacl -m user:kabir:r-x /finance
hdfs dfs -getfacl /finance
echo "-- kabir (named in the ACL): $(HADOOP_USER_NAME=kabir hdfs dfs -ls /finance 2>&1 | grep -c q3.csv) file visible"
echo "-- riya (not in the ACL): $(HADOOP_USER_NAME=riya hdfs dfs -ls /finance 2>&1 | grep -o "Permission denied: user=riya" )"
hdfs dfs -ls -d /finance | awk "{print \$1, \$3, \$8}"
hdfs dfs -rm -r -skipTrash /finance > /dev/null'
# Run on your PC: bash kerberos_lab.shReal output. The KDC log section shows the last 8 groups of requests, so it includes earlier runs of the script. Ranger is not part of this lab.
Which key opens which ticket
Follow riya's login with three keys: hers, the KDC's and the NameNode's. Each step can only be opened by one of them.
Worked examples: real problems, solved and traced in memory
Four security design problems from different organisations: naming, mapping, policies and long jobs.
Name the principals for a new cluster
Problem statement
A telecom company adds a cluster with a NameNode on nn1.blr.telco.in, 2 workers (w1, w2, each a DataNode and a NodeManager) and a ResourceManager on rm1. Realm: TELCO.IN. List the service principals they need (ignore HTTP).
nn1, rm1, w1, w2 · realm TELCO.IN
6 principals nn/nn1.blr.telco.in@TELCO.IN rm/rm1.blr.telco.in@TELCO.IN dn/w1.blr.telco.in@TELCO.IN nm/w1.blr.telco.in@TELCO.IN dn/w2.blr.telco.in@TELCO.IN nm/w2.blr.telco.in@TELCO.IN
Approach
- One principal per service per host: service/host@REALM.
- Workers run two services each.
- Count them.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Map principals to short names
Problem statement
A university's users log in as roll123@STUDENTS.UNI.AC.IN and staff as name@STAFF.UNI.AC.IN; the cluster realm is STAFF. HDFS home folders are /user/<short name>. Which short names do these principals get with “strip the realm for both realms, deny others”?
3 principals · 2 trusted realms
roll123@STUDENTS.UNI.AC.IN -> roll123 meera@STAFF.UNI.AC.IN -> meera eve@EVIL.ORG -> nobody
Approach
- Split name and realm.
- Accept the two trusted realms, strip the realm.
- Everything else maps to nobody.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
ACLs or Ranger policies?
Problem statement
A hospital has 40 departments, each with a folder under /records, and 6 roles that need read access across several departments. Count the ACL entries needed if each role is added to each folder it needs (average 25 folders per role), versus Ranger policies written per role.
6 roles · 25 folders each
ACL entries to manage : 150 Ranger policies to manage: 6 (each with a list of paths, audited centrally)
Approach
- ACL: one entry per role per folder.
- Ranger: one policy per role listing its folders.
- Compare what must be reviewed.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
A 30-hour job and 10-hour tickets
Problem statement
A bank's year-end reconciliation runs 30 hours. Tickets last 10 hours and are renewable for 7 days. HDFS delegation tokens last 24 hours unless renewed (renew interval) and at most 7 days. Which credentials expire during the job, and what keeps it alive?
job 30 h · TGT 10 h · token 24 h renew, max 7 d
TGT expires during job: True - harmless after submission delegation token renewed 1 time(s) by the RM; max life OK: True
Approach
- The client TGT is only needed at submission.
- Tasks use delegation tokens; the ResourceManager renews them.
- Check the hard 7-day maximum.
Solution: run it live
What happens in memory, step by step
Recorded from a real Python run: press Next to execute one line at a time. Watch variables change in each frame, and lists and dictionaries (numbered #1, #2 …) fill up as objects.
Check yourself
Quick revision
Lesson 12.5 in one screen
- Four pillars: authentication (Kerberos), authorization (permissions, ACLs, Ranger), audit, encryption (wire and at rest).
- Simple auth trusts the client's user name: in our lab
HADOOP_USER_NAME=hadoopdeleted a 700 folder. - Kerberos: AS_REQ → TGT (kinit), TGS_REQ → service ticket (
nn/host@REALM), service decrypts with its keytab. - Lab: no ticket → “Client cannot authenticate via:[TOKEN, KERBEROS]”; riya's ticket → files owned by riya; pretending does nothing.
- auth_to_local maps principals to short names; jobs use delegation tokens, renewed by the RM.
- ACL:
hdfs dfs -setfacl -m user:kabir:r-x; Ranger: central resource/tag policies, masking, row filters, audit. - Production: AD as KDC, keytabs locked down, clocks synced (5 min skew), RPC privacy, encryption zones + KMS, Knox.
Interview and viva questions
Why is Kerberos needed in Hadoop?
Without it Hadoop uses simple authentication: the client's user name (from the OS or HADOOP_USER_NAME) is trusted, so anyone with network access can act as any user, including the HDFS superuser. Kerberos makes every user and service prove its identity with tickets from a KDC, so permissions, ACLs and Ranger policies apply to the real person.
How does Kerberos authentication work in Hadoop?
The user runs kinit and the KDC's Authentication Service returns a ticket-granting ticket sealed with a key derived from the password. The client then asks the Ticket-Granting Service for a service ticket for a Hadoop service such as nn/host@REALM, and presents it to that service, which decrypts it with the key in its keytab. Jobs then use Hadoop delegation tokens so tasks do not contact the KDC.
What is Apache Ranger?
A central authorization and audit framework for the Hadoop ecosystem. Administrators define policies in Ranger Admin (by user, group, resource or Atlas tag); plugins inside HDFS, Hive, HBase, YARN, Kafka and others download the policies, enforce them locally and send audit events to Solr or HDFS. Ranger also supports column masking and row filtering for Hive.
What is the difference between HDFS ACLs and Ranger?
ACLs are stored on each file or directory in the NameNode and only cover HDFS. Ranger policies are defined centrally, can cover many paths and services with one policy, support groups from LDAP/AD, tags, masking and row filters, and keep a searchable audit of every decision.
What is a keytab and why is it sensitive?
A keytab stores a principal's long-term keys so a service (or a scheduled job) can log in to Kerberos without typing a password. Anyone who can read it can act as that principal until the keys are changed, so keytabs must be readable only by the service user, kept out of source control and rotated.
Practice problems
Security exercises built on the real messages and settings from our lab.
Read a principal
Split nn/nn-secure@LAB.MYPHATSHALA into service, host and realm.
one principal
nn nn-secure LAB.MYPHATSHALA
Show solution and explanation
p = "nn/nn-secure@LAB.MYPHATSHALA"
name, realm = p.split("@"); service, host = name.split("/")
print(service, host, realm)How it works: nn (the NameNode service), host nn-secure, realm LAB.MYPHATSHALA.
Ticket expiry
riya's TGT was valid from 10:08:23 for 10 hours. When does it expire?
10:08:23 + 10 h
20:08:23
Show solution and explanation
from datetime import datetime, timedelta
print((datetime(2026, 10, 22, 10, 8, 23) + timedelta(hours=10)).time())How it works: 20:08:23, exactly what klist showed.
Read the permission bits
/payroll is drwx------ owned by nn. Which of owner, group and others may enter it?
drwx------
owner can enter group cannot enter others cannot enter
Show solution and explanation
bits = "rwx------"
for who, part in zip(["owner", "group", "others"], [bits[0:3], bits[3:6], bits[6:9]]):
print(who, "can enter" if part[2] == "x" else "cannot enter")How it works: Only the owner nn; riya needed EXECUTE on the folder, hence access=EXECUTE in the error.
Effective ACL rights with a mask
The mask limits named users and groups. With user:kabir:rwx but mask::r-x, what can kabir do?
rwx AND r-x
kabir effective: r-x
Show solution and explanation
def eff(entry, mask):
return "".join(e if (e != "-" and m != "-") else "-" for e, m in zip(entry, mask))
print("kabir effective:", eff("rwx", "r-x"))How it works: r-x: the mask removes write, which is why getfacl shows the mask line.
Count KDC traffic
Each hdfs command is a new JVM that asks for a service ticket. 500 analysts each run 40 commands a day. How many TGS requests? How many AS requests if each logs in twice?
500 × 40 · 500 × 2
TGS: 20000 AS: 1000
Show solution and explanation
print("TGS:", 500 * 40, "AS:", 500 * 2)How it works: 20,000 TGS and 1,000 AS requests a day: why big companies run several KDCs (or AD domain controllers).
Clock skew
Kerberos rejects tickets if clocks differ by more than 5 minutes. Which servers fail?
offsets in seconds
['w2', 'edge1']
Show solution and explanation
offsets = {"nn1": 12, "w1": -40, "w2": 410, "edge1": -305}
print([h for h, s in offsets.items() if abs(s) > 300])How it works: w2 and edge1: “Clock skew too great”. Run NTP or chrony everywhere.
Cost of not securing
One accidental or malicious delete of a 40 TB folder takes 3 engineers 5 days to restore from DR (₹8,000 per engineer-day) plus a day of lost analytics for 200 users (₹2,000 each). Compare with a 2-week Kerberos + Ranger project for 2 engineers.
illustrative costs
one incident Rs 520,000 vs project Rs 160,000
Show solution and explanation
incident = 3 * 5 * 8000 + 200 * 2000
project = 2 * 10 * 8000
print(f"one incident Rs {incident:,} vs project Rs {project:,}")How it works: ₹5.2 lakh for one incident vs ₹1.6 lakh (illustrative), before counting audit findings or leaked data.
Simulate impersonation attempts
For each request, decide what a simple-auth and a Kerberos cluster believe the user is.
3 requests
claimed=hadoop ticket=None simple->hadoop kerberos->REJECTED claimed=nn ticket=riya simple->nn kerberos->riya claimed=None ticket=kabir simple->os-user kerberos->kabir
Show solution and explanation
reqs = [{"claimed": "hadoop", "ticket": None}, {"claimed": "nn", "ticket": "riya"}, {"claimed": None, "ticket": "kabir"}]
for r in reqs:
simple = r["claimed"] or "os-user"
kerberos = r["ticket"] or "REJECTED"
print(f"claimed={r['claimed']!s:6} ticket={r['ticket']!s:5} simple->{simple:7} kerberos->{kerberos}")How it works: Simple auth believes the claim; Kerberos only the ticket, and rejects requests without one.
Real-world scenario questions (asked in company interviews)
Security questions come up in Hadoop admin, data engineering and platform interviews, usually with a story.
“Explain Kerberos in Hadoop in two minutes”
A standard opening question.
The interviewer is checking: the three exchanges and why Hadoop needs it.
Show a strong answer
- Without Kerberos, Hadoop trusts the user name the client sends; anyone can be the superuser.
- kinit → TGT from the AS; TGT → service ticket for nn/host@REALM from the TGS; the NameNode decrypts it with its keytab.
- Jobs get delegation tokens at submission so tasks don't hit the KDC; the RM renews them.
All jobs on one worker fail with “GSS initiate failed”
Other workers are fine; nothing was deployed.
The interviewer is checking: a methodical Kerberos checklist.
Show a strong answer
- Check the clock (more than 5 minutes of skew), forward and reverse DNS of the host, and that the keytab's KVNO matches the KDC (klist -kt).
- Try kinit -kt with the service keytab on that host; enable sun.security.krb5.debug=true for the details.
- Check krb5.conf (realm, KDC address, allowed encryption types) against the working workers.
Analysts need customer data, but not phone numbers
An e-commerce company must restrict PII without blocking reports.
The interviewer is checking: masking, tags and audit, not more copies.
Show a strong answer
- Tag PII columns in Atlas; one Ranger tag policy masks them (hash or last 4 digits) for analysts, clear for an approved group.
- Row-level filters if analysts should see only their region.
- Keep HDFS paths of the raw tables closed to analysts so they cannot bypass Hive; review Ranger audit monthly.
“Our folder is 700, so it's secure, right?”
A teammate on an unsecured cluster.
The interviewer is checking: that you know permissions need authentication.
Show a strong answer
- Not on simple auth: anyone can set HADOOP_USER_NAME to the owner's name, as our lab showed with a delete.
- Permissions protect against mistakes; against people you need Kerberos (and a firewall around the cluster).
- Then add Ranger for central policies and audit, and encryption for data at rest.