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.
6 """Client tool to perform various authentication related tasks."""
13 from third_party import colorama
14 from third_party.depot_tools import fix_encoding
15 from third_party.depot_tools import subcommand
18 from utils import oauth
19 from utils import tools
22 def add_auth_options(parser):
23 """Adds command line options related to authentication."""
24 parser.auth_group = optparse.OptionGroup(parser, 'Authentication')
25 parser.auth_group.add_option(
26 '--use-cookie-auth', action='store_true',
27 help='Use cookie-based authentication instead of OAuth.')
28 parser.add_option_group(parser.auth_group)
29 oauth.add_oauth_options(parser)
32 def process_auth_options(options):
33 """Configures process-wide authentication parameters based on |options|."""
34 method = 'cookie' if options.use_cookie_auth else 'oauth'
35 net.configure_auth(method, oauth_options=options)
38 class AuthServiceError(Exception):
39 """Unexpected response from authentication service."""
42 class AuthService(object):
43 """Represents remote Authentication service."""
45 def __init__(self, url):
46 self._service = net.get_http_service(url)
49 """Refreshes cached access token or creates a new one."""
50 return self._service.login()
53 """Purges cached access token."""
54 return self._service.logout()
56 def get_current_identity(self):
57 """Returns identity associated with currently used credentials.
60 user:<email> - if using OAuth or cookie based authentication.
61 bot:<id> - if using HMAC based authentication.
62 anonymous:anonymous - if not authenticated.
64 identity = self._service.json_request('GET', '/auth/api/v1/accounts/self')
66 raise AuthServiceError('Failed to fetch identity')
67 return identity['identity']
70 @subcommand.usage('[options]')
71 def CMDlogin(parser, args):
72 """Refreshes short lived authentication token."""
73 (options, args) = parser.parse_args(args)
74 process_auth_options(options)
75 service = AuthService(options.service)
77 print 'Logged in as \'%s\'.' % service.get_current_identity()
80 print 'Login failed or canceled.'
84 @subcommand.usage('[options]')
85 def CMDlogout(parser, args):
86 """Purges cached credentials."""
87 (options, args) = parser.parse_args(args)
88 process_auth_options(options)
89 service = AuthService(options.service)
93 @subcommand.usage('[options]')
94 def CMDcheck(parser, args):
95 """Shows identity associated with currently cached credentials."""
96 (options, args) = parser.parse_args(args)
97 process_auth_options(options)
98 service = AuthService(options.service)
99 print service.get_current_identity()
102 class OptionParserAuth(tools.OptionParserWithLogging):
103 def __init__(self, **kwargs):
104 tools.OptionParserWithLogging.__init__(self, prog='auth.py', **kwargs)
105 self.server_group = tools.optparse.OptionGroup(self, 'Server')
106 self.server_group.add_option(
108 metavar='URL', default='',
109 help='Service to use')
110 self.add_option_group(self.server_group)
111 add_auth_options(self)
113 def parse_args(self, *args, **kwargs):
114 options, args = tools.OptionParserWithLogging.parse_args(
115 self, *args, **kwargs)
116 options.service = options.service.rstrip('/')
117 if not options.service:
118 self.error('--service is required.')
123 dispatcher = subcommand.CommandDispatcher(__name__)
125 return dispatcher.execute(OptionParserAuth(version=__version__), args)
126 except Exception as e:
127 tools.report_error(e)
131 if __name__ == '__main__':
132 fix_encoding.fix_encoding()
133 tools.disable_buffering()
135 sys.exit(main(sys.argv[1:]))