Index: fedd/creddy_split.py
===================================================================
--- fedd/creddy_split.py	(revision 87c0fc17072bfc099262738f77b6b3d682a5ebee)
+++ fedd/creddy_split.py	(revision 87c0fc17072bfc099262738f77b6b3d682a5ebee)
@@ -0,0 +1,79 @@
+#!/usr/local/bin/python
+
+import sys
+import re
+import os
+
+from optparse import OptionParser
+
+# Options
+class Parser(OptionParser):
+    def __init__(self):
+	OptionParser.__init__(self, usage="%prog [options] file.pem")
+	self.add_option('--cert', dest='cert', default='./cert.pem', 
+		help='File to extract certificate into, default: [%default]')
+	self.add_option('--key', dest='key', default='./key.pem', 
+		help='File to extract key into, default: [%default]')
+	self.add_option('--force', action='store_true', dest='force',
+		default=False,
+		help=('Overwite existing certificate and key files. ' + \
+			'default: [%default]'))
+
+class diversion:
+    '''
+    Wraps up the reqular expression to start and end a diversion, as well as
+    the open file that gets the lines.
+    '''
+    def __init__(self, start, end, fn):
+	self.start = re.compile(start)
+	self.end = re.compile(end)
+	self.f = open(fn, 'w')
+
+# Option validation
+parser = Parser()
+opts, args = parser.parse_args()
+
+if len(args) == 1:
+    combo = args[0]
+else:
+    parser.print_help()
+    sys.exit('\nMust have one file argument')
+
+if not opts.force:
+    for fn in (opts.cert, opts.key):
+	if os.access(fn, os.F_OK):
+	    sys.exit('%s exists.  --force to overwite it' % fn)
+
+try:
+    # Initialize the diversions
+    divs = [diversion(s, e, fn) for s, e,fn in (
+	('\s*-----BEGIN RSA PRIVATE KEY-----$', 
+	    '\s*-----END RSA PRIVATE KEY-----$',
+	    opts.key),
+	('\s*-----BEGIN CERTIFICATE-----$', 
+	    '\s*-----END CERTIFICATE-----$',
+	    opts.cert))]
+
+    # walk through the file, beginning a diversion when a start regexp matches
+    # until the end regexp matches.  While in the two regexps, print each line
+    # to the ipen diversion file (including the two matches).
+    active = None
+    f = open(combo, 'r')
+    for l in f:
+	if active:
+	    if active.end.match(l):
+		print >>active.f, l,
+		active = None
+	else:
+	    for d in divs:
+		if d.start.match(l):
+		    active = d
+		    break
+	if active: print >>active.f, l,
+
+# This clause catches all file opening problems, including the diversion opens
+except EnvironmentError, e:
+    sys.exit("%s: %s" % (e.strerror, e.filename or '?!'))
+
+# This is probably unnecessary.  Close all the diversion files.
+for d in divs: d.f.close()
Index: fedd/fedd_to_abac.py
===================================================================
--- fedd/fedd_to_abac.py	(revision 87c0fc17072bfc099262738f77b6b3d682a5ebee)
+++ fedd/fedd_to_abac.py	(revision 87c0fc17072bfc099262738f77b6b3d682a5ebee)
@@ -0,0 +1,114 @@
+#!/usr/local/bin/python
+
+import sys
+import re
+
+import os
+import os.path
+import subprocess
+
+from string import join
+from optparse import OptionParser
+
+class Parser(OptionParser):
+    def __init__(self):
+	OptionParser.__init__(self)
+	self.add_option('--cert', dest='cert', default=None,
+		help='my fedid as an X.509 certificate')
+	self.add_option('--key', dest='key', default=None,
+		help='key for the certificate')
+	self.add_option('--dir', dest='dir', default=None,
+		help='Output directory for credentials')
+	self.add_option('--make-dir', action='store_true', dest='make_dir',
+		default=False, help='Create the --dir directory')
+	self.add_option('--debug', action='store_true', dest='debug',
+		default=False, help='Just print the creddy commands')
+
+class identity:
+    def __init__(self, name, roles=None):
+	self.name = name
+	if roles: self.roles = set(roles)
+
+    def add_roles(self, roles):
+	self.roles |= set(roles)
+
+    def __str__(self):
+	return "%s: %s" % (self.name, join(self.roles, ', '))
+
+comment_re = re.compile('^\s*#|^$')
+fedid_str = 'fedid:([0-9a-fA-F]{40})'
+id_str = '[a-zA-Z][\w_-]*'
+single_re = re.compile('\s*%s\s*->\s*(%s)' % (fedid_str, id_str))
+double_re = re.compile('\s*%s\s*->\s*\((%s)\s*,\s*(%s)\)' % \
+	(fedid_str, id_str, id_str))
+bad_role = re.compile('[^a-zA-Z_]+')
+
+parser = Parser()
+opts, args = parser.parse_args()
+
+if any([ x is None for x in (opts.cert, opts.dir, opts.key)]):
+    print >>sys.stderr, "Need all of --dir, --cert, and --key to create certs"
+    print >>sys.stderr, "Reverting to debug mode"
+    debug = True
+else:
+    debug = opts.debug
+
+if opts.cert and not os.access(opts.cert, os.R_OK):
+    sys.exit('Cannot read %s (certificate file)' % opts.cert)
+
+if opts.key and not os.access(opts.key, os.R_OK):
+    sys.exit('Cannot read %s (key file)' % opts.key)
+
+if opts.dir:
+    if opts.make_dir:
+	if not os.path.isdir(opts.dir) and not debug:
+	    try:
+		os.mkdir(opts.dir, 0755)
+	    except EnvironmentError, e:
+		sys.exit('Could not make %s: %s' % (opts.dir, e))
+    else:
+	if not os.path.isdir(opts.dir):
+	    sys.exit('%s is not a directory' % opts.dir)
+	elif not os.access(opts.dir, os.W_OK):
+	    sys.exit('%s is not writable' % opts.dir)
+
+
+roles = { }
+
+for fn in args:
+    try:
+	f = open(fn, "r")
+	for l in f:
+	    id = None
+	    for r in (comment_re, single_re, double_re):
+		m = r.match(l)
+		if m: 
+		    if m.groups():
+			g = m.groups()
+			id = g[0]
+			r = [ bad_role.sub('_', x) for x in g[1:] ]
+		    break
+	    else:
+		print 'Unmatched line: %s' % l 
+	    if id:
+		if id in roles: roles[id].add_roles(r)
+		else: roles[id] = identity(r[0], r)
+
+    except EnvironmentError, e:
+	print >>sys.stderr, 'Cannot open file (%s): %e' % e
+
+for k, id in roles.items():
+    for i, r in enumerate(id.roles):
+	cmd = ['creddy', '--attribute', 
+		'--issuer=%s' % (opts.cert or 'cert_file'),
+		'--key=%s' % (opts.key or 'key_file'), '--role=%s' % r,
+		'--subject-id=%s' % k,
+		'--out=%s/%s%03d.der' % \
+			(opts.dir or 'new_cert_dir', id.name, i)]
+	if debug:
+	    print join(cmd)
+	else:
+	    rv =  subprocess.call(cmd)
+	    if rv != 0:
+		sys.exit('%s failed: %d' % (join(cmd), rv))
+
