Integrating kerberised and shibboleth based authentication: Difference between revisions
No edit summary |
No edit summary |
||
Line 2: | Line 2: | ||
Test change. |
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 == |
Revision as of 14:53, 20 March 2015
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