def client(self, address, is_cli=True): ''' Return a client given the address. Note that this can either be called by the CLI (is_cli=True) or the server (is_cli=False). If called by the CLI, we don't need to authenticate. Cache the Client if necessary. ''' if address in self.clients: return self.clients[address] # if local force mockauth or if locl server use correct auth if is_local_address(address): bundle_store = self.bundle_store() model = self.model() auth_handler = self.auth_handler(mock=is_cli) from codalab.client.local_bundle_client import LocalBundleClient client = LocalBundleClient(address, bundle_store, model, auth_handler, self.cli_verbose) self.clients[address] = client if is_cli: # Set current user access_token = self._authenticate(client) auth_handler.validate_token(access_token) else: from codalab.client.remote_bundle_client import RemoteBundleClient client = RemoteBundleClient(address, lambda a_client: self._authenticate(a_client), self.cli_verbose()) self.clients[address] = client self._authenticate(client) return client
def _authenticate(self, client): ''' Authenticate with the given client. This will prompt user for password unless valid credentials are already available. Client state will be updated if new tokens are generated. client: The client pointing to the bundle service to authenticate with. Returns an access token. ''' address = client.address auth = self.state['auth'].get(address, {}) def _cache_token(token_info, username=None): ''' Helper to update state with new token info and optional username. Returns the latest access token. ''' # Make sure this is in sync with auth.py. token_info['expires_at'] = time.time() + float(token_info['expires_in']) del token_info['expires_in'] auth['token_info'] = token_info if username is not None: auth['username'] = username self.save_state() return token_info['access_token'] # Check the cache for a valid token if 'token_info' in auth: token_info = auth['token_info'] expires_at = token_info.get('expires_at', 0.0) if expires_at > time.time(): # Token is usable but check if it's nearing expiration (10 minutes) # If not nearing, then just return it. if expires_at >= (time.time() + 10 * 60): return token_info['access_token'] # Otherwise, let's refresh the token. token_info = client.login('refresh_token', auth['username'], token_info['refresh_token']) if token_info is not None: return _cache_token(token_info) # If we get here, a valid token is not already available. auth = self.state['auth'][address] = {} username = None # For a local client with mock credentials, use the default username. if is_local_address(client.address): username = self.root_user_name() password = '' if not username: print 'Requesting access at %s' % address sys.stdout.write('Username: '******'credentials', username, password) if token_info is None: raise PermissionError("Invalid username or password.") return _cache_token(token_info, username)
def derive_rest_address(self, address): """ Given bundle service address, return corresponding REST address using manual translations (described in the comments below). Temporary hack to ease transition to REST API. """ o = urlparse(address) if is_local_address(address): # local => http://localhost:<rest_port> precondition('server' in self.config and 'rest_host' in self.config['server'] and 'rest_port' in self.config['server'], 'Working on local now requires running a local ' 'server, please configure "rest_host" and ' '"rest_port" under "server" in your config.json.') address = 'http://{rest_host}:{rest_port}'.format(**self.config['server']) elif (o.hostname == 'localhost' and 'server' in self.config and 'port' in self.config['server'] and 'rest_port' in self.config['server'] and o.port == self.config['server']['port']): # http://localhost:<port> => http://localhost:<rest_port> # Note that this does not affect the address of the NLP # CodaLab instance behind an SSH tunnel address = address.replace(str(self.config['server']['port']), str(self.config['server']['rest_port'])) elif (o.netloc == 'worksheets.codalab.org' or o.netloc == 'worksheets-test.codalab.org'): # http://worksheets.codalab.org/bundleservice => http://worksheets.codalab.org address = address.replace('/bundleservice', '') return address
def client(self, address, is_cli=True): ''' Return a client given the address. Note that this can either be called by the CLI (is_cli=True) or the server (is_cli=False). If called by the CLI, we don't need to authenticate. Cache the Client if necessary. ''' if address in self.clients: return self.clients[address] # if local force mockauth or if locl server use correct auth if is_local_address(address): bundle_store = self.bundle_store() model = self.model() auth_handler = self.auth_handler(mock=is_cli) from codalab.client.local_bundle_client import LocalBundleClient client = LocalBundleClient(address, bundle_store, model, auth_handler, self.cli_verbose) self.clients[address] = client if is_cli: # Set current user access_token = self._authenticate(client) auth_handler.validate_token(access_token) else: from codalab.client.remote_bundle_client import RemoteBundleClient client = RemoteBundleClient( address, lambda a_client: self._authenticate(a_client), self.cli_verbose()) self.clients[address] = client self._authenticate(client) return client
def _authenticate(self, client): ''' Authenticate with the given client. This will prompt user for password unless valid credentials are already available. Client state will be updated if new tokens are generated. client: The client pointing to the bundle service to authenticate with. Returns an access token. ''' address = client.address auth = self.state['auth'].get(address, {}) def _cache_token(token_info, username=None): ''' Helper to update state with new token info and optional username. Returns the latest access token. ''' token_info['expires_at'] = time.time() + float(token_info['expires_in']) - 60.0 del token_info['expires_in'] auth['token_info'] = token_info if username is not None: auth['username'] = username self.save_state() return token_info['access_token'] # Check the cache for a valid token if 'token_info' in auth: token_info = auth['token_info'] expires_at = token_info.get('expires_at', 0.0) if expires_at > time.time(): # Token is usable but check if it's nearing expiration if expires_at >= (time.time() + 900.0): return token_info['access_token'] # Try to refresh token token_info = client.login('refresh_token', auth['username'], token_info['refresh_token']) if token_info is not None: return _cache_token(token_info) # If we get here, a valid token is not already available. auth = self.state['auth'][address] = {} # For a local client with mock credentials, use the default username. username = '' if is_local_address(client.address): from codalab.server.auth import MockAuthHandler if type(self.auth_handler()) is MockAuthHandler: username = '******' password = '' if not username: print 'Requesting access at %s' % address print 'Username: '******'credentials', username, password) if token_info is None: raise UsageError("Invalid username or password") return _cache_token(token_info, username)
def client(self, address, is_cli=True, use_rest=False): ''' Return a client given the address. Note that this can either be called by the CLI (is_cli=True) or the server (is_cli=False). If called by the CLI, we don't need to authenticate. Cache the Client if necessary. ''' # FIXME(sckoo): temporary hack # When BundleCLI is no longer dependent on RemoteBundleClient # or LocalBundleClient, simplify everything to only using # JsonApiClient, and remove all use_rest kwargs. # Users should also then update their aliases to point at the # correct addresses of the REST servers. if use_rest: address = self.derive_rest_address(address) # Return cached client # TODO(sckoo): Remove is_cli check when REST migration complete if not is_cli and address in self.clients: return self.clients[address] # Create new client if use_rest: # Create RestOAuthHandler that authenticates directly with # OAuth endpoints on the REST server from codalab.server.auth import RestOAuthHandler auth_handler = RestOAuthHandler(address, None) # Create JsonApiClient with a callback to get access tokens from codalab.client.json_api_client import JsonApiClient client = JsonApiClient( address, lambda: self._authenticate(address, auth_handler)) elif is_local_address(address): # if local force mockauth or if local server use correct auth bundle_store = self.bundle_store() model = self.model() worker_model = self.worker_model() upload_manager = self.upload_manager() download_manager = self.download_manager() auth_handler = self.auth_handler(mock=is_cli) from codalab.client.local_bundle_client import LocalBundleClient client = LocalBundleClient(address, bundle_store, model, worker_model, upload_manager, download_manager, auth_handler, self.cli_verbose) if is_cli: # Set current user access_token = self._authenticate(client.address, client.auth_handler) auth_handler.validate_token(access_token) else: from codalab.client.remote_bundle_client import RemoteBundleClient client = RemoteBundleClient(address, lambda a_client: self._authenticate(a_client.address, a_client), self.cli_verbose) self._authenticate(client.address, client) # Cache and return client self.clients[address] = client return client
def _authenticate(self, client): ''' Authenticate with the given client. This will prompt user for password unless valid credentials are already available. Client state will be updated if new tokens are generated. client: The client pointing to the bundle service to authenticate with. Returns an access token. ''' address = client.address auth = self.state['auth'].get(address, {}) def _cache_token(token_info, username=None): ''' Helper to update state with new token info and optional username. Returns the latest access token. ''' # Make sure this is in sync with auth.py. token_info['expires_at'] = time.time() + float( token_info['expires_in']) del token_info['expires_in'] auth['token_info'] = token_info if username is not None: auth['username'] = username self.save_state() return token_info['access_token'] # Check the cache for a valid token if 'token_info' in auth: token_info = auth['token_info'] expires_at = token_info.get('expires_at', 0.0) if expires_at > time.time(): # Token is usable but check if it's nearing expiration (10 minutes) # If not nearing, then just return it. if expires_at >= (time.time() + 10 * 60): return token_info['access_token'] # Otherwise, let's refresh the token. token_info = client.login('refresh_token', auth['username'], token_info['refresh_token']) if token_info is not None: return _cache_token(token_info) # If we get here, a valid token is not already available. auth = self.state['auth'][address] = {} username = None # For a local client with mock credentials, use the default username. if is_local_address(client.address): username = self.root_user_name() password = '' if not username: print 'Requesting access at %s' % address sys.stdout.write('Username: '******'credentials', username, password) if token_info is None: raise PermissionError("Invalid username or password.") return _cache_token(token_info, username)