X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=ud-host;h=79a9bd105516dfd3bd16a4c3fa3d1b48e04d6937;hb=refs%2Fheads%2Ffordsa;hp=7255960e56fdcd2c8804d22bb58aee5d6803488a;hpb=709fd2d1d8ed92c0b4474706fa7b09d06ca00238;p=mirror%2Fuserdir-ldap.git diff --git a/ud-host b/ud-host index 7255960..79a9bd1 100755 --- a/ud-host +++ b/ud-host @@ -4,7 +4,8 @@ # Copyright (c) 2000-2001 Jason Gunthorpe # Copyright (c) 2001 Ryan Murray # Copyright (c) 2003 James Troup -# Copyright (c) 2004 Joey Schulze +# Copyright (c) 2004-2005 Joey Schulze +# Copyright (c) 2008,2009 Peter Palfrader # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -29,11 +30,14 @@ # -a Set the authentication user (the user whose password you are # going to enter) # -h Set the host to display +# -l list all hosts and their status +# -f list all SSH fingerprints -import string, time, os, pwd, sys, getopt, ldap, crypt, whrandom, readline, copy; -from userdir_ldap import *; +import time, os, pwd, sys, getopt, ldap, crypt, readline, copy, subprocess +from os import O_CREAT, O_EXCL, O_WRONLY +from userdir_ldap import * -RootMode = 0; +RootMode = 0 AttrInfo = {"description": ["Machine Descr.", 1], "hostname": ["Host names", 2], "status": ["Status", 3], @@ -46,8 +50,17 @@ AttrInfo = {"description": ["Machine Descr.", 1], "machine": ["Machine Hardware", 10], "memory": ["Memory", 11], "disk": ["Disk", 12], + "physicalHost": ["Physical Host", 13], "sshRSAHostKey": ["SSH Host Keys", 14], - "bandwidth": ["Bandwidth", 15]}; + "bandwidth": ["Bandwidth", 15], + "purpose": ["Purposes", 16], + "allowedGroups": ["Groups", 17], + "exportOptions": ["Export-Opts", 18], + "ipHostNumber": ["IP Address", 19], + "mXRecord": ["MXRecord", 20], + "dnsTTL": ["dnsTTL", 21], + "sshdistAuthKeysHost": ["extra authkeys ip", 22], + } AttrPrompt = {"description": ["Purpose of the machine"], "hostname": ["The hostnames for the box (ipv4/ipv6)"], @@ -61,35 +74,44 @@ AttrPrompt = {"description": ["Purpose of the machine"], "machine": ["Hardware description"], "memory": ["Installed RAM"], "disk": ["Disk Space, RAID levels, etc"], - "sshRSAHostKey": ["A copy of /etc/ssh/ssh_*host_key.pub"], - "bandwidth": ["Available outbound"]}; + "physicalHost": ["The box hosting this virtual server"], + "sshRSAHostKey": ["A copy of /etc/ssh/ssh_*host_key.pub"], + "bandwidth": ["Available outbound"], + "purpose": ["The purposes of this host"], + "allowedGroups": ["allowed Groups on this host"], + "exportOptions": ["additional export options"], + "ipHostNumber": ["IP Addresses(es) of the machine"], + "mXRecord": ["Mail Exchanger for this machine"], + "dnsTTL": ["dns TTL value"], + "sshdistAuthKeysHost": ["additional hosts for sshdist's authkeys file"], + } # Create a map of IDs to desc,value,attr -OrderedIndex = {}; +OrderedIndex = {} for at in AttrInfo.keys(): if (AttrInfo[at][1] != 0): - OrderedIndex[AttrInfo[at][1]] = [AttrInfo[at][0], "", at]; -OrigOrderedIndex = copy.deepcopy(OrderedIndex); + OrderedIndex[AttrInfo[at][1]] = [AttrInfo[at][0], "", at] +OrigOrderedIndex = copy.deepcopy(OrderedIndex) # Print out the automatic time stamp information def PrintModTime(Attrs): - Stamp = GetAttr(Attrs,"modifyTimestamp",""); + Stamp = GetAttr(Attrs,"modifyTimestamp","") if len(Stamp) >= 13: Time = (int(Stamp[0:4]),int(Stamp[4:6]),int(Stamp[6:8]), - int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1); + int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1) print "%-24s:" % ("Record last modified on"), time.strftime("%a %d/%m/%Y %X UTC",Time), - print "by",ldap.explode_dn(GetAttr(Attrs,"modifiersName"),1)[0]; + print "by",ldap.explode_dn(GetAttr(Attrs,"modifiersName"),1)[0] - Stamp = GetAttr(Attrs,"createTimestamp",""); + Stamp = GetAttr(Attrs,"createTimestamp","") if len(Stamp) >= 13: Time = (int(Stamp[0:4]),int(Stamp[4:6]),int(Stamp[6:8]), - int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1); - print "%-24s:" % ("Record created on"), time.strftime("%a %d/%m/%Y %X UTC",Time); + int(Stamp[8:10]),int(Stamp[10:12]),int(Stamp[12:14]),0,0,-1) + print "%-24s:" % ("Record created on"), time.strftime("%a %d/%m/%Y %X UTC",Time) # Display all of the attributes in a numbered list def ShowAttrs(Attrs): - print; - PrintModTime(Attrs); + print + PrintModTime(Attrs) for at in Attrs[1].keys(): if AttrInfo.has_key(at): @@ -97,127 +119,137 @@ def ShowAttrs(Attrs): print " %-18s:" % (AttrInfo[at][0]), for x in Attrs[1][at]: print "'%s'" % (x), - print; + print else: - OrderedIndex[AttrInfo[at][1]][1] = Attrs[1][at]; + OrderedIndex[AttrInfo[at][1]][1] = Attrs[1][at] - Keys = OrderedIndex.keys(); - Keys.sort(); + Keys = OrderedIndex.keys() + Keys.sort() for at in Keys: if at < 100 or RootMode != 0: print " %3u) %-18s: " % (at,OrderedIndex[at][0]), for x in OrderedIndex[at][1]: print "'%s'" % (re.sub('[\n\r]','?',x)), - print; + print def Overview(Attrs): """Display a one-line overview for a given host""" - if 'status' in Attrs[1].keys(): - status = Attrs[1]['status'][0] - else: - status = '' + for i in ['host','architecture','distribution','access','status']: + if i not in Attrs[1].keys(): + Attrs[1][i] = [''] print "%-12s %-10s %-38s %-25s %s" % (\ Attrs[1]['host'][0], \ Attrs[1]['architecture'][0], \ Attrs[1]['distribution'][0], \ Attrs[1]['access'][0], \ - status) + Attrs[1]['status'][0]) # Change a single attribute def ChangeAttr(Attrs,Attr): - if (Attr == "sponsor" or Attr == "hostname" or Attr == "sshRSAHostKey"): - return MultiChangeAttr(Attrs,Attr); + if (Attr in ["sponsor", "sshRSAHostKey", "purpose", "allowedGroups", "exportOptions", "ipHostNumber", "mXRecord", "sshdistAuthKeysHost"]): + return MultiChangeAttr(Attrs,Attr) - print "Old value: '%s'" % (GetAttr(Attrs,Attr,"")); - print "Press enter to leave unchanged and a single space to set to empty"; - NewValue = raw_input("New? "); + print "Old value: '%s'" % (GetAttr(Attrs,Attr,"")) + print "Press enter to leave unchanged and a single space to set to empty" + NewValue = raw_input("New? ") # Empty string if (NewValue == ""): - print "Leaving unchanged."; - return; + print "Leaving unchanged." + return # Single space designates delete, trap the delete error if (NewValue == " "): - print "Deleting.",; + print "Deleting.", try: - l.modify_s(HostDn,[(ldap.MOD_DELETE,Attr,None)]); + l.modify_s(HostDn,[(ldap.MOD_DELETE,Attr,None)]) except ldap.NO_SUCH_ATTRIBUTE: - pass; + pass - print; - Attrs[1][Attr] = [""]; - return; + print + Attrs[1][Attr] = [""] + return # Set a new value - print "Setting.",; - l.modify_s(HostDn,[(ldap.MOD_REPLACE,Attr,NewValue)]); - Attrs[1][Attr] = [NewValue]; - print; + print "Setting.", + l.modify_s(HostDn,[(ldap.MOD_REPLACE,Attr,NewValue)]) + Attrs[1][Attr] = [NewValue] + print def MultiChangeAttr(Attrs,Attr): # Make sure that we have an entry if not Attrs[1].has_key(Attr): - Attrs[1][Attr] = []; + Attrs[1][Attr] = [] - Attrs[1][Attr].sort(); - print "Old values: ",Attrs[1][Attr]; + Attrs[1][Attr].sort() + print "Old values: ",Attrs[1][Attr] - Mode = string.upper(raw_input("[D]elete or [A]dd? ")); + Mode = raw_input("[D]elete or [A]dd? ").upper() if (Mode != 'D' and Mode != 'A'): - return; + return - NewValue = raw_input("Value? "); + NewValue = raw_input("Value? ") # Empty string if (NewValue == ""): - print "Leaving unchanged."; - return; + print "Leaving unchanged." + return # Delete if (Mode == "D"): - print "Deleting.",; + print "Deleting.", try: - l.modify_s(HostDn,[(ldap.MOD_DELETE,Attr,NewValue)]); + l.modify_s(HostDn,[(ldap.MOD_DELETE,Attr,NewValue)]) except ldap.NO_SUCH_ATTRIBUTE: - print "Failed"; + print "Failed" - print; - Attrs[1][Attr].remove(NewValue); - return; + print + Attrs[1][Attr].remove(NewValue) + return # Set a new value - print "Setting.",; - l.modify_s(HostDn,[(ldap.MOD_ADD,Attr,NewValue)]); - Attrs[1][Attr].append(NewValue); - print; + print "Setting.", + l.modify_s(HostDn,[(ldap.MOD_ADD,Attr,NewValue)]) + Attrs[1][Attr].append(NewValue) + print + # Main program starts here -User = pwd.getpwuid(os.getuid())[0]; -BindUser = User; +User = pwd.getpwuid(os.getuid())[0] +BindUser = User +ListMode = 0 +FingerPrints = 0 +Host = None # Process options -(options, arguments) = getopt.getopt(sys.argv[1:], "nh:a:rl") +try: + (options, arguments) = getopt.getopt(sys.argv[1:], "nh:a:rlf") +except getopt.GetoptError, data: + print data + sys.exit(1) + for (switch, val) in options: if (switch == '-h'): - Host = val; + Host = val elif (switch == '-a'): - BindUser = val; + BindUser = val elif (switch == '-r'): - RootMode = 1; + RootMode = 1 elif (switch == '-n'): - BindUser = ""; + BindUser = "" elif (switch == '-l'): + BindUser = "" ListMode = 1 + elif (switch == '-f'): + BindUser = "" + FingerPrints = 1 if (BindUser != ""): - l = passwdAccessLDAP(LDAPServer, BaseDn, BindUser) + l = passwdAccessLDAP(BaseDn, BindUser) else: - l = ldap.open(LDAPServer); + l = connectLDAP() l.simple_bind_s("","") -HBaseDn = "ou=hosts,dc=debian,dc=org"; - if ListMode == 1: - Attrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=*") + Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=*") hosts = [] for hAttrs in Attrs: hosts.append(hAttrs[1]['host'][0]) @@ -230,101 +262,125 @@ if ListMode == 1: if host == hAttrs[1]['host'][0]: Overview(hAttrs) sys.exit(0) +elif FingerPrints == 1: + if Host is not None: + Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host) + else: + Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=*") + hosts = [] + for hAttrs in Attrs: + hosts.append(hAttrs[1]['host'][0]) + hosts.sort() -HostDn = "host=" + Host + "," + HBaseDn; + for host in hosts: + for hAttrs in Attrs: + if host == hAttrs[1]['host'][0]: + if 'sshRSAHostKey' in hAttrs[1].keys(): + for key in hAttrs[1]['sshRSAHostKey']: + keygen = subprocess.Popen(['/usr/bin/ssh-keygen', '-l', '-f', '-'], + stdin=subprocess.PIPE, stdout=subprocess.PIPE) + keygen.stdin.write(key + '\n') + keygen.stdin.close() + input = keygen.stdout.readline() + keygen.wait() + fingerprint = input.split(' ') + print "%s %s root@%s" % (fingerprint[0], fingerprint[1], host) + sys.exit(0) + +HostDn = "host=" + Host + "," + HostBaseDn # Query the server for all of the attributes -Attrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host); +Attrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + Host) if len(Attrs) == 0: - print "Host",Host,"was not found."; - sys.exit(0); + print "Host",Host,"was not found." + sys.exit(0) # repeatedly show the account configuration while(1): - ShowAttrs(Attrs[0]); + ShowAttrs(Attrs[0]) if (BindUser == ""): - sys.exit(0); + sys.exit(0) if RootMode == 1: - print " a) Arbitary Change"; - print " n) New Host"; - print " d) Delete Host"; - print " u) Switch Hosts"; - print " x) Exit"; + print " a) Arbitary Change" + print " n) New Host" + print " d) Delete Host" + print " u) Switch Hosts" + print " x) Exit" # Prompt - Response = raw_input("Change? "); + Response = raw_input("Change? ") if (Response == "x" or Response == "X" or Response == "q" or Response == "quit" or Response == "exit"): - break; + break # Change who we are looking at if (Response == 'u' or Response == 'U'): - NewHost = raw_input("Host? "); + NewHost = raw_input("Host? ") if NewHost == "": - continue; - NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost); + continue + NAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost) if len(NAttrs) == 0: - print "Host",NewHost,"was not found."; - continue; - Attrs = NAttrs; - Host = NewHost; - HostDn = "host=" + Host + "," + HBaseDn; - OrderedIndex = copy.deepcopy(OrigOrderedIndex); - continue; + print "Host",NewHost,"was not found." + continue + Attrs = NAttrs + Host = NewHost + HostDn = "host=" + Host + "," + HostBaseDn + OrderedIndex = copy.deepcopy(OrigOrderedIndex) + continue # Create a new entry and change to it Change who we are looking at if (Response == 'n' or Response == 'N'): - NewHost = raw_input("Host? "); + NewHost = raw_input("Host? ") if NewHost == "": - continue; - NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost); + continue + NAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost) if len(NAttrs) != 0: - print "Host",NewHost,"already exists."; - continue; - NewHostName = raw_input("Hostname? "); + print "Host",NewHost,"already exists." + continue + NewHostName = raw_input("Hostname? ") if NewHost == "": - continue; - Dn = "host=" + NewHost + "," + HBaseDn; + continue + Dn = "host=" + NewHost + "," + HostBaseDn l.add_s(Dn,[("host", NewHost), ("hostname", NewHostName), - ("objectClass", ("top", "debianServer"))]); + ("objectClass", ("top", "debianServer"))]) # Switch - NAttrs = l.search_s(HBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost); + NAttrs = l.search_s(HostBaseDn,ldap.SCOPE_ONELEVEL,"host=" + NewHost) if len(NAttrs) == 0: - print "Host",NewHost,"was not found."; - continue; - Attrs = NAttrs; - Host = NewHost; - HostDn = "host=" + Host + "," + HBaseDn; - OrderedIndex = copy.deepcopy(OrigOrderedIndex); - continue; + print "Host",NewHost,"was not found." + continue + Attrs = NAttrs + Host = NewHost + HostDn = "host=" + Host + "," + HostBaseDn + OrderedIndex = copy.deepcopy(OrigOrderedIndex) + continue # Handle changing an arbitary value if (Response == "a"): - Attr = raw_input("Attr? "); - ChangeAttr(Attrs[0],Attr); - continue; + Attr = raw_input("Attr? ") + ChangeAttr(Attrs[0],Attr) + continue if (Response == 'd'): - Really = raw_input("Really (type yes)? "); + Really = raw_input("Really (type yes)? ") if Really != 'yes': - continue; - print "Deleting",HostDn; - l.delete_s(HostDn); - continue; + continue + print "Deleting",HostDn + l.delete_s(HostDn) + continue # Convert the integer response try: - ID = int(Response); + ID = int(Response) if (not OrderedIndex.has_key(ID) or (ID > 100 and RootMode == 0)): - raise ValueError; + raise ValueError except ValueError: - print "Invalid"; - continue; + print "Invalid" + continue # Print the what to do prompt - print "Changing LDAP entry '%s' (%s)" % (OrderedIndex[ID][0],OrderedIndex[ID][2]); - print AttrPrompt[OrderedIndex[ID][2]][0]; - ChangeAttr(Attrs[0],OrderedIndex[ID][2]); + print "Changing LDAP entry '%s' (%s)" % (OrderedIndex[ID][0],OrderedIndex[ID][2]) + print AttrPrompt[OrderedIndex[ID][2]][0] + ChangeAttr(Attrs[0],OrderedIndex[ID][2])