[811bc273] | 1 | #!/usr/local/bin/python |
---|
| 2 | |
---|
| 3 | import sys |
---|
| 4 | import os |
---|
| 5 | |
---|
| 6 | from M2Crypto import SSL |
---|
| 7 | from M2Crypto.SSL import SSLError |
---|
| 8 | from xmlrpclib import ServerProxy, dumps, loads, Fault, Error, Binary |
---|
| 9 | |
---|
| 10 | # This disables server hostname checking in SSL as a side effect. |
---|
| 11 | from cred_printer.util import ssl_context, SSLTransport |
---|
| 12 | |
---|
| 13 | from string import join |
---|
| 14 | from optparse import OptionParser |
---|
| 15 | |
---|
| 16 | |
---|
| 17 | class OptParser(OptionParser): |
---|
| 18 | """ |
---|
| 19 | Option parsing for clients. Should be self-explanatory. |
---|
| 20 | """ |
---|
| 21 | def __init__(self): |
---|
| 22 | OptionParser.__init__(self) |
---|
| 23 | if 'CRED_URL' in os.environ: default_url = os.environ['CRED_URL'] |
---|
| 24 | else: default_url = 'http://localhost:13232' |
---|
| 25 | |
---|
| 26 | self.add_option('--url', dest='url', default=default_url, |
---|
| 27 | help='URL of the server') |
---|
| 28 | self.add_option('--cert', dest='cert', default=None, |
---|
| 29 | help='My identity certificate (and key)') |
---|
| 30 | self.add_option('--verbose', dest='verbose', default=False, |
---|
| 31 | action='store_true') |
---|
| 32 | |
---|
| 33 | def print_attr(a, label): |
---|
| 34 | ''' |
---|
| 35 | Print the fields of an attribute dict |
---|
| 36 | ''' |
---|
| 37 | print '\t%s:' % label |
---|
| 38 | for an in ('pretty_principal', 'principal', 'role', 'linked_role'): |
---|
| 39 | if an in a: print '\t\t%s: %s' % (an, a[an]) |
---|
| 40 | |
---|
| 41 | def print_cred(e, verbose=False): |
---|
| 42 | ''' |
---|
| 43 | Print the credential (e), either as one line of |
---|
| 44 | id type string auxstring |
---|
| 45 | or |
---|
| 46 | id Error, code n |
---|
| 47 | |
---|
| 48 | If verbose is True, print the head and tail components of valid attribute |
---|
| 49 | credentials indented. |
---|
| 50 | ''' |
---|
| 51 | |
---|
| 52 | if e['errcode'] == 0: |
---|
| 53 | print "%s: %s %s %s" % (e['id'], e['type'], e['str'], e['auxstr']) |
---|
| 54 | if verbose and e['type'] == 'attribute': |
---|
| 55 | for en in ('head', 'tail'): |
---|
| 56 | if en in e: print_attr(e[en], en) |
---|
| 57 | else: |
---|
| 58 | print "%s: Error, code %d" % (e['id'], e['errcode']) |
---|
| 59 | |
---|
| 60 | |
---|
| 61 | # Parse the args |
---|
| 62 | parser = OptParser() |
---|
| 63 | opts, args = parser.parse_args() |
---|
| 64 | |
---|
| 65 | if opts.cert: |
---|
| 66 | # If a certificate is given, use an SSL-protected connection |
---|
| 67 | try: |
---|
| 68 | ctx = ssl_context(opts.cert) |
---|
| 69 | except SSLError, e: |
---|
| 70 | sys.exit("Cannot load %s: %s" % (opts.cert, e)) |
---|
| 71 | |
---|
| 72 | transport=SSLTransport(ctx) |
---|
| 73 | else: |
---|
| 74 | transport=None |
---|
| 75 | |
---|
| 76 | |
---|
| 77 | creds = [] |
---|
| 78 | for fn in args: |
---|
| 79 | # Collect the contents of the filenames into the creds list |
---|
| 80 | try: |
---|
| 81 | # The list comprehension and join are a compact way to read the whole |
---|
| 82 | # file into a string. |
---|
| 83 | creds.append(join([l for l in open(fn)], '')) |
---|
| 84 | except EnvironmentError, e: |
---|
| 85 | # warn if there's an error reading one of the files |
---|
| 86 | print >>sys.stderr, "Cannot read %s: %s" % (fn, e.strerror) |
---|
| 87 | |
---|
| 88 | # This builds a list of structs with the ID (an integer printed to 3 places) |
---|
| 89 | # and the contents of the file as an XMLRPC binary. |
---|
| 90 | req = [ {'id': "%03d" % i, 'credential': Binary(c) } |
---|
| 91 | for i, c in enumerate(creds)] |
---|
| 92 | |
---|
| 93 | # Call the server |
---|
| 94 | proxy = ServerProxy(opts.url, transport=transport) |
---|
| 95 | try: |
---|
| 96 | resp = proxy.translate(req) |
---|
| 97 | except SSLError, e: |
---|
| 98 | sys.exit("SSL error: %s" %e) |
---|
| 99 | except EnvironmentError, e: |
---|
| 100 | sys.exit("IOError: %s" %e) |
---|
| 101 | except: |
---|
| 102 | t, e = sys.exc_info()[0:2] |
---|
| 103 | sys.exit('Unexpected error: %s %s' % (t,e)) |
---|
| 104 | |
---|
| 105 | # Sort by ID |
---|
| 106 | resp.sort(key=lambda x: x['id']) |
---|
| 107 | |
---|
| 108 | # Output the response |
---|
| 109 | for e in resp: |
---|
| 110 | print_cred(e, opts.verbose) |
---|