Merge remote branch 'origin/master'
authorAlex Dehnert <adehnert@mit.edu>
Sat, 15 Dec 2012 10:10:38 +0000 (05:10 -0500)
committerAlex Dehnert <adehnert@mit.edu>
Sat, 15 Dec 2012 10:10:38 +0000 (05:10 -0500)
* origin/master:
  mail-merge: remind people to cd to the examples
  ldapfinger: show how to use ldaps and ldap-too
  Instructions for using mail-merge
  Install scripts read-only
  Update Makefile and README to reflect removed scripts
  Remove list-members
  Remove check-host script
  Remove card-access script
  Optionally show queries used in list-of-lists-updater
  Remove pag-screen, since it's maintained elsewhere
  Add sendmail-based mail merger
  Refactor out the actual mail-sending

compute-list-closure [new file with mode: 0755]
sort-lines [new file with mode: 0755]
sshroot

diff --git a/compute-list-closure b/compute-list-closure
new file mode 100755 (executable)
index 0000000..cfbc771
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+
+import moira
+import sys
+import Queue
+
+def lenient_query(*query):
+    try:
+        results = moira.query(*query)
+    except moira.MoiraException as e:
+        msg = e[1]
+        if msg == 'No records in database match query':
+            results = []
+        else:
+            raise
+    return results
+    
+
+def expand_closure(lst, owns=True, members=True, member_of=True, recursive=True, ):
+    closure = set()
+    include_type = 'list'
+    if recursive: include_type = 'rlist'
+    if owns:
+        results = lenient_query('get_ace_use', include_type, lst)
+        for result in results:
+            if result['use_type'] == 'LIST':
+                closure.add(result['use_name'])
+
+    if members:
+        results = lenient_query('get_members_of_list', lst)
+        for result in results:
+            if result['member_type'] == 'LIST':
+                closure.add(result['member_name'])
+
+    if member_of:
+        results = lenient_query('get_lists_of_member', include_type, lst)
+        for result in results:
+            closure.add(result['list_name'])
+
+    return closure
+
+def get_exclusions(lst):
+    exclusions = set()
+    results = lenient_query('get_members_of_list', lst)
+    for result in results:
+        if result['member_type'] == 'LIST':
+            exclusions.add(result['member_name'])
+    return exclusions
+
+def compute_closure(lists, exclude):
+    closure = set()
+    parent = {}
+
+    the_queue = Queue.Queue()
+    for lst in lists:
+        the_queue.put(lst)
+    for lst in lists:
+        parent[lst] = None
+
+    while not the_queue.empty():
+        lst = the_queue.get()
+        if lst in closure:
+            print "skipping %s" % (lst, )
+            continue
+        closure.add(lst)
+        try:
+            new_lists = expand_closure(lst, member_of=False, recursive=False, )
+        except moira.MoiraException as e:
+            msg = e[1]
+            if msg == 'Insufficient permission to perform requested database access':
+                new_lists = []
+                print >>sys.stderr, "List %s (parent %s) appears to be hidden; ignoring. (Queue length: %d; closure length: %d)" % (lst, parent[lst], the_queue.qsize(), len(closure), )
+            else:
+                raise
+        for new_list in new_lists:
+            if new_list in closure:
+                pass
+            elif new_list in exclude:
+                print "Excluding %s (parent %s)" % (new_list, lst)
+            else:
+                the_queue.put(new_list)
+                parent[new_list] = lst
+                print "%s (from %s)" % (new_list, lst)
+    return closure
+
+if __name__ == '__main__':
+    moira.connect()
+    moira.auth('awdflu') # client name is awdflu --- Alex Dehnert file-lists-updater
+    starter_list = sys.argv[1]
+    exclude_list = sys.argv[2]
+    exclude = get_exclusions(exclude_list)
+    closure = compute_closure([starter_list], exclude)
+    moira.disconnect()
+    print "\n\n\n"
+    for lst in closure:
+        print lst
+    print
+    print "Count:", len(closure)
diff --git a/sort-lines b/sort-lines
new file mode 100755 (executable)
index 0000000..8f3b466
--- /dev/null
@@ -0,0 +1,71 @@
+#!/usr/bin/python
+import collections
+import csv
+import sys
+
+class SortFile(object):
+    def __init__(self, code, descr, ):
+        self._fd = None
+        self.code = code
+        self.descr = descr
+
+    def filename(self, ):
+        return "%s.txt" % (self.descr, )
+
+    def getFD(self, ):
+        if not self._fd:
+            self._fd = open(self.filename(), 'a')
+        return self._fd
+
+    def close(self, ):
+        if self._fd:
+            self._fd.close()
+            self._fd = None
+
+
+def read_options(filename):
+    fd = open(filename, 'r')
+    reader = csv.DictReader(fd, dialect='excel-tab', )
+    cats = {}
+    for line in reader:
+        cats[line['code']] = SortFile(code=line['code'], descr=line['descr'])
+    return cats
+
+def process_line(line, cats, dest):
+    print line,
+    count = 0
+    for code, dest in cats.items():
+        if count % 4 == 0: print ""
+        print "(%s) %16s\t\t" % ( code, dest.descr, ),
+        count += 1
+    print ""
+    need_choice = True
+    while need_choice:
+        choice = raw_input("Enter your choice:")
+        if choice == " ":
+            if dest:
+                dest.getFD().write(line)
+                need_choice = False
+        elif choice in cats:
+            dest = cats[choice]
+            dest.getFD().write(line)
+            need_choice = False
+
+def process(infile, cats):
+    fd = open(infile, 'r')
+    dest = None
+    lineno = 0
+    for line in fd:
+        lineno += 1
+        try:
+            dest = process_line(line, cats, dest)
+        except KeyboardInterrupt:
+            print "\n\nCurrent line number:", lineno
+            raise
+
+if __name__ == "__main__":
+    cats_file = sys.argv[1]
+    data_file = sys.argv[2]
+    cats = read_options(cats_file)
+    print cats
+    process(data_file, cats)
diff --git a/sshroot b/sshroot
index 6a0c4b5f6e8d906e1d572c75e54a7e3a2b78adf5..f4d8996ffc2044745e1ae8d0553715657c6c9a13 100755 (executable)
--- a/sshroot
+++ b/sshroot
@@ -1,24 +1,40 @@
 #!/bin/bash
-export KRB5CCNAME=/tmp/krb5cc_$(id -u).root
-export KRBTKFILE=/dev/null
 
-lifetime=900
+# lifetime, in minutes
+lifetime=15
+keysuffix=root
+
 hostopt=""
 [ -z "$hostopt" ] && hostopt="${HOSTNAME}"
 [ -z "$hostopt" ] && hostopt=`uname -n 2>/dev/null || echo unknown`
-keys=~/.ssh/id_rsa_root
+
+while getopts "H:k:l:" opt; do
+    case "$opt" in
+    H)  hostopt="$OPTARG";;
+    k)  keysuffix="$OPTARG";;
+    l)  lifetime="$OPTARG";;
+    \?) die "$0 [-H hostname] [-k keysuffix] [-l lifetime]"
+    esac
+done
+shift $(($OPTIND - 1))
+
+keys="$HOME/.ssh/id_rsa_$keysuffix"
+keychain_host="$hostopt-$keysuffix"
 
 function with-keys
 {
     unset SSH_AUTH_SOCK SSH_AGENT_PID
-    eval $(keychain --eval --host "$hostopt-root" $keys)
+    eval $(keychain --timeout "$lifetime" --eval --host "$keychain_host" $keys)
+    export SSHROOT=1
     exec "$@"
 }
 
 function with-agent
 {
     unset SSH_AUTH_SOCK SSH_AGENT_PID
-    eval $(keychain --eval --host "$hostopt-root")
+    eval $(keychain --timeout "$lifetime" --eval --host "$keychain_host")
+    export SSHROOT=1
+    echo with-agent: Running: "$@"
     exec "$@"
 }
 
@@ -28,11 +44,11 @@ shift
 case "$command" in
     init)
         echo "Loading default keys (lifetime $lifetime)..."
-        with-agent ssh-add -t $lifetime "$@" $keys
+        with-agent ssh-add -t "${lifetime}m" "$@" $keys
         ;;
     add)
         echo "Loading keys (lifetime $lifetime):" "$@"
-        with-agent ssh-add -t $lifetime "$@"
+        with-agent ssh-add -t "${lifetime}m" "$@"
         ;;
     list)
         with-agent ssh-add -l
@@ -41,10 +57,11 @@ case "$command" in
         with-agent ssh-add -D
         ;;
     shell)
-        with-keys $SHELL
+        with-keys "$SHELL" "$@"
         ;;
     ssh)
-        with-keys ssh -l root "$@"
+        #with-keys ssh -l root "$@"
+        with-keys ssh "$@"
         ;;
     *)
         if [ -z "$command" ]; then