source: fedd/fedd_to_abac.py @ a0c2866

axis_examplecompt_changesinfo-ops
Last change on this file since a0c2866 was 62f3dd9, checked in by Ted Faber <faber@…>, 14 years ago

allow command line progams to expand tildes. Added a class derived from OptionParser? to make that easily available.

  • Property mode set to 100755
File size: 3.8 KB
Line 
1#!/usr/local/bin/python
2
3import sys
4import re
5
6import os
7import os.path
8import subprocess
9
10from string import join
11
12from federation.util import abac_pem_type, abac_split_cert, file_expanding_opts
13
14class Parser(file_expanding_opts):
15    def __init__(self):
16        file_expanding_opts.__init__(self)
17        self.add_option('--cert', dest='cert', default=None,
18                action='callback', callback=self.expand_file, type='str',
19                help='my fedid as an X.509 certificate')
20        self.add_option('--key', dest='key', default=None,
21                action='callback', callback=self.expand_file, type='str',
22                help='key for the certificate')
23        self.add_option('--dir', dest='dir', default=None,
24                action='callback', callback=self.expand_file, type='str',
25                help='Output directory for credentials')
26        self.add_option('--make-dir', action='store_true', dest='make_dir',
27                default=False, help='Create the --dir directory')
28        self.add_option('--debug', action='store_true', dest='debug',
29                default=False, help='Just print the creddy commands')
30
31class identity:
32    def __init__(self, name, roles=None):
33        self.name = name
34        if roles: self.roles = set(roles)
35
36    def add_roles(self, roles):
37        self.roles |= set(roles)
38
39    def __str__(self):
40        return "%s: %s" % (self.name, join(self.roles, ', '))
41
42comment_re = re.compile('^\s*#|^$')
43fedid_str = 'fedid:([0-9a-fA-F]{40})'
44id_str = '[a-zA-Z][\w_-]*'
45single_re = re.compile('\s*%s\s*->\s*(%s)' % (fedid_str, id_str))
46double_re = re.compile('\s*%s\s*->\s*\((%s)\s*,\s*(%s)\)' % \
47        (fedid_str, id_str, id_str))
48bad_role = re.compile('[^a-zA-Z0-9_]+')
49
50parser = Parser()
51opts, args = parser.parse_args()
52cert, key = None, None
53delete_certs = False
54
55
56
57if opts.key:
58    if os.access(opts.key, os.R_OK): key = opts.key
59    else: sys.exit('Cannot read %s (key file)' % opts.key)
60
61if opts.dir:
62    if opts.make_dir:
63        if not os.path.isdir(opts.dir) and not debug:
64            try:
65                os.mkdir(opts.dir, 0755)
66            except EnvironmentError, e:
67                sys.exit('Could not make %s: %s' % (opts.dir, e))
68    else:
69        if not os.path.isdir(opts.dir):
70            sys.exit('%s is not a directory' % opts.dir)
71        elif not os.access(opts.dir, os.W_OK):
72            sys.exit('%s is not writable' % opts.dir)
73
74if opts.cert:
75    if os.access(opts.cert, os.R_OK):
76        if not key:
77            if abac_pem_type(opts.cert) == 'both':
78                key, cert = abac_split_cert(opts.cert)
79                delete_certs = True
80        else:
81            cert = opts.cert
82    else:
83        sys.exit('Cannot read %s (certificate file)' % opts.cert)
84
85if any([ x is None for x in (cert, opts.dir, key)]):
86    print >>sys.stderr, "Need output dir, certificate and key to make creds"
87    print >>sys.stderr, "Reverting to debug mode"
88    debug = True
89else:
90    debug = opts.debug
91
92roles = { }
93try:
94    for fn in args:
95        try:
96            f = open(fn, "r")
97            for l in f:
98                id = None
99                for r in (comment_re, single_re, double_re):
100                    m = r.match(l)
101                    if m: 
102                        if m.groups():
103                            g = m.groups()
104                            id = g[0]
105                            r = [ bad_role.sub('_', x) for x in g[1:] ]
106                        break
107                else:
108                    print 'Unmatched line: %s' % l
109                if id:
110                    # New and create are implicit.  >sigh<
111                    r.extend(('new', 'create'))
112                    if id in roles: roles[id].add_roles(r)
113                    else: roles[id] = identity(r[0], r)
114
115        except EnvironmentError, e:
116            print >>sys.stderr, 'Cannot open file (%s): %s' % \
117                    (e.filename, e.strerror)
118
119    if not roles:
120        print >>sys.stderr, "No roles found.  Did you specify a configuration?"
121
122    for k, id in roles.items():
123        for i, r in enumerate(id.roles):
124            cmd = ['creddy', '--attribute', 
125                    '--issuer=%s' % (cert or 'cert_file'),
126                    '--key=%s' % (key or 'key_file'), '--role=%s' % r,
127                    '--subject-id=%s' % k,
128                    '--out=%s/%s%03d_attr.der' % \
129                            (opts.dir or 'new_cert_dir', id.name, i)]
130            if debug:
131                print join(cmd)
132            else:
133                rv =  subprocess.call(cmd)
134                if rv != 0:
135                    sys.exit('%s failed: %d' % (join(cmd), rv))
136finally:
137    if delete_certs:
138        if cert: os.unlink(cert)
139        if key: os.unlink(key)
Note: See TracBrowser for help on using the repository browser.