Chromium Code Reviews| Index: appengine/swarming/swarming_bot/bot_code/bot_auth.py |
| diff --git a/appengine/swarming/swarming_bot/bot_code/bot_auth.py b/appengine/swarming/swarming_bot/bot_code/bot_auth.py |
| index 20627a48ccfb1b187a3b3e41df82a5de23a1c9a8..8fccd37e1e59806aaf088c8158bdad2d88cbd20b 100644 |
| --- a/appengine/swarming/swarming_bot/bot_code/bot_auth.py |
| +++ b/appengine/swarming/swarming_bot/bot_code/bot_auth.py |
| @@ -4,6 +4,12 @@ |
| import collections |
| +import file_reader |
| + |
| + |
| +class AuthSystemError(Exception): |
| + """Fatal errors raised by AuthSystem class.""" |
| + |
| # Parsed value of JSON at path specified by --auth-params-file task_runner arg. |
| AuthParams = collections.namedtuple('AuthParams', [ |
| @@ -59,3 +65,79 @@ def process_auth_params_json(val): |
| headers = {str(k): str(v) for k, v in headers.iteritems()} |
| return AuthParams(headers) |
| + |
| + |
| +class AuthSystem(object): |
|
Vadim Sh.
2016/08/31 03:53:32
I couldn't come up with a better name...
I want a
M-A Ruel
2016/08/31 15:03:46
BigBrother. :D
|
| + """Authentication subsystem used by task_runner. |
| + |
| + Contains two threads: |
| + * One thread periodically rereads the file with bots own authentication |
| + information (auth_params_file). This file is generated by bot_main. |
| + * Another thread hosts local HTTP server that servers authentication tokens |
| + to local processes. |
| + |
| + The local HTTP server exposes /prpc/LuciLocalAuthService.GetOAuthToken |
| + endpoint that the processes running inside Swarming tasks can use to request |
| + an OAuth access token associated with the task. |
| + |
| + They can discover the port to connect to by looking at LUCI_CONTEXT |
| + environment variable. |
| + |
| + TODO(vadimsh): Actually implement the second thread and LUCI_CONTEXT. |
| + """ |
| + |
| + def __init__(self): |
| + self._auth_params_reader = None |
|
M-A Ruel
2016/08/31 15:03:46
you should guard it with a threading.Lock()
Vadim Sh.
2016/09/01 00:15:56
Done. Though I think its overkill in Python. GIL e
|
| + |
| + def start(self, auth_params_file): |
| + """Grabs initial bot auth headers and starts all auth related threads. |
| + |
| + Args: |
| + auth_params_file: path to a file with AuthParams dict, update by bot_main. |
| + |
| + Raises: |
| + AuthSystemError on fatal errors. |
| + """ |
| + assert not self._auth_params_reader, 'already running' |
| + try: |
| + # Read headers more often than bot_main writes them (which is 60 sec), to |
| + # reduce maximum possible latency between header updates and reads. Use |
| + # interval that isn't a divisor of 60 to avoid reads and writes happening |
| + # at the same moment in time. |
| + reader = file_reader.FileReaderThread(auth_params_file, interval_sec=23) |
|
M-A Ruel
2016/08/31 15:03:46
Why not 53?
Vadim Sh.
2016/09/01 00:15:56
Dunno. Changed to 53. It's not really important.
|
| + reader.start() |
| + except file_reader.FatalReadError as e: |
| + raise AuthSystemError('Cannot start FileReaderThread: %s' % e) |
| + |
| + # Initial validation. |
| + try: |
| + process_auth_params_json(reader.last_value) |
| + except ValueError as e: |
| + reader.stop() |
| + raise AuthSystemError('Cannot parse bot_auth_params.json: %s' % e) |
| + |
| + # Good to go. |
| + self._auth_params_reader = reader |
| + |
| + def stop(self): |
| + """Shuts down all the threads if they are running.""" |
| + if self._auth_params_reader: |
| + self._auth_params_reader.stop() |
| + self._auth_params_reader = None |
| + |
| + @property |
| + def bot_headers(self): |
| + """A dict with HTTP headers that contain bots own credentials. |
| + |
| + Such headers can be sent to Swarming server's /bot/* API. Must be used only |
| + after 'start' and before 'stop'. |
| + |
| + Raises: |
| + AuthSystemError if auth_params_file is suddenly no longer valid. |
| + """ |
| + assert self._auth_params_reader, '"start" was not called' |
| + try: |
| + val = process_auth_params_json(self._auth_params_reader.last_value) |
| + return val.swarming_http_headers |
| + except ValueError as e: |
| + raise AuthSystemError('Cannot parse bot_auth_params.json: %s' % e) |