Integrating kerberised and shibboleth based authentication

From Lsdf
Revision as of 14:53, 20 March 2015 by Alex b (talk | contribs)
Jump to navigationJump to search

Die web authorisierung von benutzer basiert am KIT auf shibboleth und idp. Allerdings gibt es eine menge 'legacy' produkten und services wofuer eine integration mit dieses neue verfahren erforderlich ist. Damit Linux und Linux services weiterhin mit der web welt mithalten koennen soll in dieses projekt untersucht werden wie das Network File System (NFS) transparent integriert werden kan in die neue KIT authorisirung.

Test change.

General scheme how to add Kerberos authentication to service

1. Add the service account to LDAP with random password, for example nfs/iwrcgop1.fzk.de@TEST.KIT.EDU:

dn: uid=nfs1,ou=users,ou=fed,dc=test,dc=kit,dc=edu
objectClass: top
objectClass: organizationalUnit
objectClass: krb5kdcentry
objectClass: uidObject
objectClass: krb5principal
krb5KeyVersionNumber: 0
krb5PrincipalName: nfs1/iwrcgop1.fzk.de@TEST.KIT.EDU
ou: NFS1
uid: nfs1
userPassword: KJ983432989bfjsbJHdab4

2. Get service keys in keytab format. An example of a script:

#!/usr/bin/env python2
# Alexander Bersenev, bay@hackerdom.ru, 2015

# 1. Gets a keys from the service 
# 2. Prints the keys in the keytab format
# Works only with apacheDS

from pyasn1.codec.der import decoder

import ldap
import random
import sys
import user
import re
import string
import struct
import time

LDAP_URI = "ldap://host.kit.edu:10389"
USERS_DN = "ou=users,ou=fed,dc=test,dc=kit,dc=edu"
REALM = "TEST.KIT.EDU"

def get_user_keys_classes_and_passwd(user, ldap_obj):
	"""Tries to get a key and password from ldap"""

	keys = []
	classes = []
	passwd = None

	user_dn = ("uid=%s," % user) + USERS_DN

	# make a ldap search request
	pairs = ldap_obj.search_s(user_dn, ldap.SCOPE_BASE)
	if len(pairs) != 1:
		# wrong LDAP scheme
		print("Multiple users")
		return keys, classes, passwd

	dn, attrs = pairs[0]

	if "krb5Key" in attrs:
		keys = attrs["krb5Key"]
	if "objectClass" in attrs:
		classes = attrs["objectClass"]
	if "userPassword" in attrs:
		passwd = attrs["userPassword"]

	return keys, classes, passwd


def put_and_get_keys(user):
	keys = None
	try:
		l = ldap.initialize(LDAP_URI)

		keys, classes, passwd = get_user_keys_classes_and_passwd(user, l)
		if keys:
			return keys

	except ldap.NO_SUCH_OBJECT:
		print("No such user")
		return keys
	except ldap.OBJECT_CLASS_VIOLATION as E:
		print("Object class violation")
		# print(E)
	except ldap.LDAPError as E:
		print("LDAP Error")
		# print(E)
		return keys

def gen_keytab(keys, service, host):
	entries = []

	for key_type, key_val in keys:
		entry = ""

		entry += struct.pack(">H", 2)  # number of components
		entry += struct.pack(">H", len(REALM))
		entry += REALM
		entry += struct.pack(">H", len(service))
		entry += service
		entry += struct.pack(">H", len(host))
		entry += host
		entry += struct.pack(">L", 1)  # name type(1 is KRB5_NT_PRINCIPAL)
		entry += struct.pack(">L", int(time.time()))  # generation time
		entry += struct.pack("B", 1)  # key version
		entry += struct.pack(">H", key_type)
		entry += struct.pack(">H", len(key_val))
		entry += key_val

		entry = struct.pack(">L", len(entry)) + entry

		entries.append(entry)

	keytab = "\x05\x02"  # version of the format
	keytab += "".join(entries)

	return keytab

def main(user, service, host):
	keys = put_and_get_keys(user)
	if not keys:
		return

	decoded_keys = []
	for key in keys:
		try:
			key_type, key_val = decoder.decode(key)[0]
			key_type = int(key_type)
			key_val = str(key_val)

			decoded_keys.append((key_type, key_val))
		except Exception:
			print("Passing a bad key")
			pass

	sys.stdout.write(gen_keytab(decoded_keys, service, host))

if __name__ == "__main__":
	if len(sys.argv) != 4:
		print("USAGE: ./get_service_key.py <user> <service> <host>")
		sys.exit(1)
	user, service, host = sys.argv[1:]
	if not re.match(r"[ a-zA-Z0-9_-]+$", user):
		print("User name validation failed")
		sys.exit(1)
	if len(user) > 16384:
		print("User name is too long")
		sys.exit(1)

	main(user, service, host)

3. Specify the service to use Kerberos and provide generated keytab file(the default path is usually /etc/krb5.keytab)

4. Set up additional service-specific things. For example, in the case of NFS, make users resolvable via LDAP


NFS Specifics