Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / swarming_client / auth.py
1 #!/usr/bin/env python
2 # Copyright 2013 The Swarming Authors. All rights reserved.
3 # Use of this source code is governed under the Apache License, Version 2.0 that
4 # can be found in the LICENSE file.
5
6 """Client tool to perform various authentication related tasks."""
7
8 __version__ = '0.3.1'
9
10 import optparse
11 import sys
12
13 from third_party import colorama
14 from third_party.depot_tools import fix_encoding
15 from third_party.depot_tools import subcommand
16
17 from utils import on_error
18 from utils import net
19 from utils import oauth
20 from utils import tools
21
22
23 class AuthServiceError(Exception):
24   """Unexpected response from authentication service."""
25
26
27 class AuthService(object):
28   """Represents remote Authentication service."""
29
30   def __init__(self, url):
31     self._service = net.get_http_service(url)
32
33   def login(self, allow_user_interaction):
34     """Refreshes cached access token or creates a new one."""
35     return self._service.login(allow_user_interaction)
36
37   def logout(self):
38     """Purges cached access token."""
39     return self._service.logout()
40
41   def get_current_identity(self):
42     """Returns identity associated with currently used credentials.
43
44     Identity is a string:
45       user:<email> - if using OAuth or cookie based authentication.
46       bot:<id> - if using HMAC based authentication.
47       anonymous:anonymous - if not authenticated.
48     """
49     identity = self._service.json_request('GET', '/auth/api/v1/accounts/self')
50     if not identity:
51       raise AuthServiceError('Failed to fetch identity')
52     return identity['identity']
53
54
55 def add_auth_options(parser):
56   """Adds command line options related to authentication."""
57   parser.auth_group = optparse.OptionGroup(parser, 'Authentication')
58   parser.auth_group.add_option(
59       '--auth-method',
60       metavar='METHOD',
61       default=net.get_default_auth_config()[0],
62       help='Authentication method to use: %s. [default: %%default]' %
63           ', '.join(name for name, _ in net.AUTH_METHODS))
64   parser.add_option_group(parser.auth_group)
65   oauth.add_oauth_options(parser)
66
67
68 def process_auth_options(parser, options):
69   """Configures process-wide authentication parameters based on |options|."""
70   # Validate that authentication method is known.
71   if options.auth_method not in dict(net.AUTH_METHODS):
72     parser.error('Invalid --auth-method value: %s' % options.auth_method)
73
74   # Process the rest of the flags based on actual method used.
75   # Only oauth is configurable now.
76   config = None
77   if options.auth_method == 'oauth':
78     config = oauth.extract_oauth_config_from_options(options)
79
80   # Now configure 'net' globally to use this for every request.
81   net.configure_auth(options.auth_method, config)
82
83
84 def ensure_logged_in(server_url):
85   """Checks that user is logged in, asking to do it if not.
86
87   Aborts the process with exit code 1 if user is not logged it. Noop when used
88   on bots.
89   """
90   if net.get_auth_method() not in ('cookie', 'oauth'):
91     return
92   server_url = server_url.lower().rstrip('/')
93   assert server_url.startswith(('https://', 'http://localhost:')), server_url
94   service = AuthService(server_url)
95   service.login(False)
96   identity = service.get_current_identity()
97   if identity == 'anonymous:anonymous':
98     print >> sys.stderr, (
99         'Please login to %s: \n'
100         '  python auth.py login --service=%s' % (server_url, server_url))
101     sys.exit(1)
102   email = identity.split(':')[1]
103   print >> sys.stderr, 'Logged in to %s: %s' % (server_url, email)
104
105
106 @subcommand.usage('[options]')
107 def CMDlogin(parser, args):
108   """Runs interactive login flow and stores auth token/cookie on disk."""
109   (options, args) = parser.parse_args(args)
110   process_auth_options(parser, options)
111   service = AuthService(options.service)
112   if service.login(True):
113     print 'Logged in as \'%s\'.' % service.get_current_identity()
114     return 0
115   else:
116     print 'Login failed or canceled.'
117     return 1
118
119
120 @subcommand.usage('[options]')
121 def CMDlogout(parser, args):
122   """Purges cached auth token/cookie."""
123   (options, args) = parser.parse_args(args)
124   process_auth_options(parser, options)
125   service = AuthService(options.service)
126   service.logout()
127   return 0
128
129
130 @subcommand.usage('[options]')
131 def CMDcheck(parser, args):
132   """Shows identity associated with currently cached auth token/cookie."""
133   (options, args) = parser.parse_args(args)
134   process_auth_options(parser, options)
135   service = AuthService(options.service)
136   service.login(False)
137   print service.get_current_identity()
138   return 0
139
140
141 class OptionParserAuth(tools.OptionParserWithLogging):
142   def __init__(self, **kwargs):
143     tools.OptionParserWithLogging.__init__(self, prog='auth.py', **kwargs)
144     self.server_group = tools.optparse.OptionGroup(self, 'Server')
145     self.server_group.add_option(
146         '-S', '--service',
147         metavar='URL', default='',
148         help='Service to use')
149     self.add_option_group(self.server_group)
150     add_auth_options(self)
151
152   def parse_args(self, *args, **kwargs):
153     options, args = tools.OptionParserWithLogging.parse_args(
154         self, *args, **kwargs)
155     options.service = options.service.rstrip('/')
156     if not options.service:
157       self.error('--service is required.')
158     on_error.report_on_exception_exit(options.service)
159     return options, args
160
161
162 def main(args):
163   dispatcher = subcommand.CommandDispatcher(__name__)
164   return dispatcher.execute(OptionParserAuth(version=__version__), args)
165
166
167 if __name__ == '__main__':
168   fix_encoding.fix_encoding()
169   tools.disable_buffering()
170   colorama.init()
171   sys.exit(main(sys.argv[1:]))