source: TI12-security/trunk/python/ndg.security.client/ndg/security/client/ndgSessionClient.py @ 4855

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.client/ndg/security/client/ndgSessionClient.py@4855
Revision 4855, 14.8 KB checked in by pjkersha, 11 years ago (diff)
  • Got rid of additional refs to Q Public licence in headers
  • Added ndg.security.server.wsgi.openid.relyingparty package and started OpenIDRelyingPartyMiddleware wrapper to AuthKit?
  • fixed classfactory import bug
  • tested Attribute Authority over SSL with mod_wsgi with AA and SM client unit tests
  • Property svn:executable set to *
  • Property svn:keywords set to Id
Line 
1#!/usr/bin/env python
2
3"""NDG Session client script - makes requests for authentication and
4authorisation
5
6NERC DataGrid Project
7"""
8__author__ = "P J Kershaw"
9__date__ = "08/03/06"
10__copyright__ = "(C) 2009 Science and Technology Facilities Council"
11__license__ = "BSD - see LICENSE file in top-level directory"
12__contact__ = "Philip.Kershaw@stfc.ac.uk"
13__revision__ = "$Id$"
14
15# Command line processing
16import sys
17import os
18import optparse
19import re
20import getpass
21
22from Cookie import SimpleCookie
23
24from ndg.security.client.SecurityClient import *
25
26
27#_____________________________________________________________________________
28def setSoapDebug(option, optStr, value, parser):
29    """Parser Callback function for enabling SOAP debug output"""
30    parser.values.soapDebug = sys.stderr
31
32   
33#_____________________________________________________________________________
34def setSessCookie(option, optStr, value, parser):
35    """Parser Callback function for reading session cookie from command line
36    """
37    try:
38        parser.values.sessCookie = SimpleCookie(open(value).read().strip())
39       
40    except IOError, (errNo, errMsg):
41        raise optparse.OptionValueError(\
42                    "Reading cookie from file \"%s\": %s" % (value, errMsg))
43                           
44    except Exception, e:
45        raise optparse.OptionValueError(\
46                    "Reading cookie from file \"%s\": %s" % (value, str(e)))
47
48
49#_____________________________________________________________________________
50def setSessCookieFromStdin(option, optStr, value, parser):
51    """Parser Callback function for reading cookie from stdin"""
52    try:
53        # Read from standard input
54        parser.values.sessCookie = SimpleCookie(sys.stdin.read().strip())
55
56    except KeyboardInterrupt:
57        raise optparse.OptionValueError(\
58                    "option \"%s\": expecting cookie set from stdin" % optStr)
59         
60    except Exception, e:
61        raise optparse.OptionValueError(\
62                    "option %s: Reading cookie from file \"%s\": %s" % \
63                    (optStr, value, str(e)))
64                   
65
66#_____________________________________________________________________________
67def setClntPriKeyPwd(option, optStr, value, parser):
68    """Parser Callback function for reading client private key password"""
69
70    try:
71        parser.values.clntPriKeyPwd = open(value).read().strip()
72       
73    except IOError, (errNo, errMsg):
74        raise optparse.OptionValueError(\
75                    "Reading password from file \"%s\": %s" % (value, errMsg))
76                           
77    except Exception, e:
78        raise optparse.OptionValueError(\
79                    "Reading password from file \"%s\": %s" % (value, str(e)))
80       
81
82#_____________________________________________________________________________
83def setAAcert(option, optStr, value, parser):
84    """Parser callback function for reading Attribute Authority Public key"""
85   
86    try:
87        parser.values.aaCert = open(value).read().strip()
88       
89    except IOError, (errNo, errMsg):
90        raise optparse.OptionValueError(\
91                "Reading Attribute Authority Public key file \"%s\": %s" % \
92                (value, errMsg))
93                           
94    except Exception, e:
95        raise optparse.OptionValueError(\
96                "Reading Attribute Authority Public key file \"%s\": %s" % \
97                (value, str(e)))
98               
99                     
100#_____________________________________________________________________________
101def main():
102
103    usage = os.path.basename(sys.argv[0]) + " [--add-user=<username> ...]|"+\
104            "[--connect=<username> ...]|[--req-attr ...]|" + \
105            "[--connect=<username> ... --req-attr ...]"
106           
107    parser = optparse.OptionParser(usage=usage)
108    parser.add_option("-n", 
109                      "--add-user", 
110                      dest="newUserName",
111                      help="add a new user, see also: -p and -s options")
112
113    parser.add_option("-c", 
114                      "--connect",
115                      dest="userName",
116                      help="""login in to a Session Manager with username.""")
117   
118    parser.add_option("-r", 
119                      "--req-attr", 
120                      dest="attributeAuthorityURI", 
121                      help=\
122"""Get a Session Manager to request authorisation from an Attribute Authority
123with the given address.""")
124   
125    parser.add_option("-a", 
126                      "--att-authority-pubkey-file",
127                      action="callback",
128                      callback=setAAcert,
129                      dest="aaCert",
130                      type="string", 
131                      help=\
132"""File Path of Public key of Attribute Authority used by the Session Manager
133to encrypt requests to it.  WARNING: If this is not set, requests will be sent
134in clear text.""")
135
136    parser.add_option("-x",
137                      "--clnt-pubkey-file",
138                      dest="clntCertFilePath",
139                      help=\
140"""X.509 Certificate of client.  This is used by the Session Manager to
141encrypt responses.  WARNING: If this is not set, the response will be sent
142back in clear text""")
143
144    parser.add_option("-k",
145                      "--clnt-prikey-file",
146                      dest="clntPriKeyFilePath",
147                      help=\
148"""Private key file of client.  This is used by the client to decrypt
149responses.  This must be set if -x/--clnt-pubkey-file is set.""")
150
151    parser.add_option("-w",
152                      "--clnt-prikey-pwd-file",
153                      dest="clntPriKeyPwd",
154                      action="callback",
155                      callback=setClntPriKeyPwd,
156                      type="string",
157                      help=\
158"""Pass a file containing the password for the client private key.  If not
159set, it is prompted for from tty.""")
160
161    parser.add_option("-y",
162                      "--session-mgr-pubkey-file",
163                      dest="smCertFilePath",
164                      help=\
165"""X.509 Certificate of Session Manager.  This is used to encrypt the request
166to the Session Manager.  WARNING: if this is not set, the request will be sent
167in clear text""")
168
169    parser.add_option("-s",
170                      "--session-mgr-uri",
171                      dest="sessMgrURI",
172                      help="Address of Session Manager to connect to")
173
174    parser.add_option("-d",
175                      "--soap-debug",
176                      dest="soapDebug",
177                      action="callback",
178                      callback=setSoapDebug,
179                      help="Print SOAP message output")
180
181    parser.add_option("-p",
182                      "--pass-phrase-from-stdin",
183                      action="store_true",
184                      dest="bPassPhraseFromStdin",
185                      default=False,
186                      help="""\
187Take user's pass-phrase from stdin.  If this flag is omitted, pass-phrase is
188prompted for from tty""")
189
190    parser.add_option("-i",
191                      "--cookie-file",
192                      action="callback",
193                      callback=setSessCookie,
194                      type="string",
195                      dest="sessCookie",
196                      help=\
197"""Session cookie for --req-attr/-r call.  This is returned from a previous
198connect call (-c USERNAME/--connect=USERNAME).  Note that connect and request
199authoirsation calls can be combined.  In this case, this arg is not needed as
200the cookie is passed directly from the connect call output to the
201authorisation request e.g. ... -c username -r -s "http://..." -a
202"http://...""")
203
204    parser.add_option("-e",
205                      "--cookie-from-stdin",
206                      action="callback",
207                      callback=setSessCookieFromStdin,
208                      dest="sessCookie",
209                      help="Read session cookie from stdin.")
210
211    parser.add_option("-m",
212                      "--map-from-trusted-hosts",
213                      action="store_true",
214                      dest="mapFromTrustedHosts",
215                      default=False,
216                      help=\
217"""For use with --req-attr/-r flag.  Set to allow the Session Manager to
218automatically use Attribute Certificates from the user's wallet or, if no
219suitable ones are found, to contact other trusted hosts in order to get
220Attribute Certificates for mapping""")
221
222    parser.add_option("-q",
223                      "--req-role",
224                      dest="reqRole",
225                      help="""\
226For use with --req-attr/-r flag.  Making certifcate mapping more efficient
227by specifying to the Session Manager what role is needed for attribute
228certificates from trusted hosts in order to get a mapped Attribute Certificate
229back from the Attribute Authority""")
230
231    parser.add_option("-l",
232                      "--rtn-ext-att-cert-list",
233                      action="store_true",
234                      dest="rtnExtAttCertList",
235                      default=False,
236                      help=\
237"""For use with --req-attr/-r flag.  Determines behaviour in the case where
238authorisation is denied by an Attribute Authority.  If set, a list of
239candidate Attribute Certificates from trusted hosts will be returned.  Any one
240of these could be re-input in a subsequent authorisation request by setting
241the --ext-att-cert-list-file option.  The certificates can be used to obtain a
242mapped Attribute Certificate from the import target Attribute Authority""")
243
244    parser.add_option("-f",
245                      "--ext-att-cert-list-file",
246                      dest="extAttCertListFile",
247                      help=\
248"""For use with --req-attr/-r flag.  A file of concatenated Attribute
249Certificates.  These are certificates from other import hosts trusted by the
250Attribute Authority.  The Session Manager tries each in turn until the
251Attribute Authority accepts one and uses it to create and return a mapped
252Attribute Certificate""")
253   
254    parser.add_option("-t",
255                      "--ext-trusted-hosts-file",
256                      dest="extTrustedHostsFile",
257                      help=\
258"""For use with --req-attr/-r flag.  Pass a file containing a comma
259separarated list of hosts that are trusted by the Attribute Authority.  The
260Session Manager will contact these hosts in turn, stopping when one of them
261grants it an Attribute Certificate that it can present to the target Attribute
262Authority in order to get a mapped Attribute Certificate in return.""")
263
264    (options, args) = parser.parse_args()
265
266    if not options.sessMgrURI:       
267        sys.stderr.write("Error, No Session Manager WSDL URI set.\n\n")
268        parser.print_help()
269        return(1)
270       
271    passPhrase = None
272   
273    # For connect/addUser a pass-phrase is needed
274    if options.newUserName or options.userName:
275       
276        if options.bPassPhraseFromStdin:
277            # Read from standard input
278            passPhrase = sys.stdin.read().strip()           
279        else:
280            # Obtain from prompt
281            try:
282                passPhrase = getpass.getpass(prompt="Login pass-phrase: ") 
283            except KeyboardInterrupt:
284                return(1)
285
286    if options.clntPriKeyPwd is None and options.clntPriKeyFilePath:
287        # Obtain from prompt
288        try:
289            options.clntPriKeyPwd = getpass.getpass(\
290                                    prompt="Client private key pass-phrase: ") 
291        except KeyboardInterrupt:
292            return(1)
293
294                 
295    extAttCertList = None
296               
297    if options.extAttCertListFile:
298        try:
299            # Open and read file removing any <?xml ... ?> headers
300            sExtAttCertListFile = open(options.extAttCertListFile).read()
301            sAttCertTmp = re.sub("\s*<\?xml.*\?>\s*", "", sExtAttCertListFile)
302           
303            # Convert into a list
304            extAttCertList = ['<attributeCertificate>' + ac for ac in \
305                            sAttCertTmp.split('<attributeCertificate>')[1:]]
306        except Exception, e:
307            sys.stderr.write(\
308                "Error parsing file \%s\" for option \"%s\": %s" % \
309                (arg, "--ext-att-cert-list-file\"/\"-f", str(e)))
310
311       
312    extTrustedHostList = None
313
314    if options.extTrustedHostsFile:
315        try:
316            extTrustedHostList = \
317                re.split("\s*,\s*", open(options.extTrustedHostsFile).read())
318           
319        except Exception, e:
320            sys.stderr.write(\
321                "Error parsing file \%s\" for option \"%s\": %s" % \
322                (arg, "--ext-trusted-host-file\"/\"-t", str(e)))
323
324
325    # Initialise session client
326    try:
327        sessClnt = SessionManagerClient(smWSDL=options.sessMgrURI,
328                             smCertFilePath=options.smCertFilePath,
329                             clntCertFilePath=options.clntCertFilePath,
330                             clntPriKeyFilePath=options.clntPriKeyFilePath,
331                             tracefile=options.soapDebug)
332    except Exception, e:
333        sys.stderr.write("Initialising client: %s\n" % str(e))
334        return(1)
335   
336    methodCall = False   
337    try:
338        if options.newUserName:
339            methodCall = True
340           
341            sessClnt.addUser(userName=options.newUserName, 
342                             pPhrase=passPhrase,
343                             clntPriKeyPwd=options.clntPriKeyPwd)
344            return(0)
345                           
346        if options.userName:
347            methodCall = True
348           
349            sSessCookie = sessClnt.connect(userName=options.userName, 
350                                       pPhrase=passPhrase,
351                                       clntPriKeyPwd=options.clntPriKeyPwd)           
352            print sSessCookie
353            # Don't exit here - req-autho may have been set too
354           
355        if options.attributeAuthorityURI:
356            methodCall = True
357
358            if options.userName:
359                # Connect was set also - parse cookie in order to session ID
360                # and WSDL address
361                options.sessCookie = SimpleCookie(sSessCookie)
362               
363            authResp = sessClnt.reqAuthorisation(\
364                            sessCookie=options.sessCookie,
365                            aaWSDL=options.attributeAuthorityURI,
366                            aaCert=options.aaCert,
367                            mapFromTrustedHosts=options.mapFromTrustedHosts,
368                            reqRole=options.reqRole,
369                            rtnExtAttCertList=options.rtnExtAttCertList,
370                            extAttCertList=extAttCertList,
371                            extTrustedHostList=extTrustedHostList,
372                            clntPriKeyPwd=options.clntPriKeyPwd)
373            print authResp
374       
375        if not methodCall:   
376            sys.stderr.write("Set a flag to specify the web-service call " + \
377                             "e.g. --connect=USERNAME\n\n")
378            parser.print_help()
379            return(1)
380           
381    except Exception, e:
382        sys.stderr.write(str(e) + os.linesep)
383     
384    return(0)
Note: See TracBrowser for help on using the repository browser.