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