def get_repositories_setuped(token, install_id): # pragma: no cover repositories = [] url = ("https://api.%s/user/installations/%s/repositories" % (config.GITHUB_DOMAIN, install_id)) token = "token {}".format(token) session = requests.Session() while True: response = session.get( url, headers={ "Authorization": token, "Accept": "application/vnd.github.machine-man-preview+json", "User-Agent": "PyGithub/Python" }) if response.status_code == 200: repositories.extend(response.json()["repositories"]) if "next" in response.links: url = response.links["next"]["url"] continue else: return repositories elif response.status_code == 403: raise github.BadCredentialsException(status=response.status_code, data=response.text) elif response.status_code == 404: raise github.UnknownObjectException(status=response.status_code, data=response.text) raise github.GithubException(status=response.status_code, data=response.text)
def get_installation_id(integration, owner, repo=None, account_type=None): if not account_type and not repo: raise RuntimeError("repo or account_type must be passed") if repo: url = "https://api.%s/repos/%s/%s/installation" % ( config.GITHUB_DOMAIN, owner, repo, ) else: url = "https://api.%s/%s/%s/installation" % ( config.GITHUB_DOMAIN, "users" if account_type.lower() == "User" else "orgs", owner, ) token = "Bearer {}".format(integration.create_jwt()) response = requests.get( url, headers={ "Authorization": token, "Accept": "application/vnd.github.machine-man-preview+json", "User-Agent": "PyGithub/Python", }, ) if response.status_code == 200: return response.json()["id"] elif response.status_code == 403: raise github.BadCredentialsException(status=response.status_code, data=response.text) elif response.status_code == 404: raise github.UnknownObjectException(status=response.status_code, data=response.text) raise github.GithubException(status=response.status_code, data=response.text)
def get_installations(integration): # pragma: no cover # FIXME(sileht): This is currently always mocked in tests installs = [] url = "https://api.github.com/app/installations" token = "Bearer {}".format(integration.create_jwt()) session = requests.Session() while True: response = session.get( url, headers={ "Authorization": token, "Accept": "application/vnd.github.machine-man-preview+json", "User-Agent": "PyGithub/Python" }) if response.status_code == 200: installs.extend(response.json()) if "next" in response.links: url = response.links["next"]["url"] continue else: return installs elif response.status_code == 403: raise github.BadCredentialsException(status=response.status_code, data=response.text) elif response.status_code == 404: raise github.UnknownObjectException(status=response.status_code, data=response.text) raise github.GithubException(status=response.status_code, data=response.text)
def test_are_creds_valid_with_invalid_creds(self): with patch.object(github.Github, 'get_user') as patched_get_user: mocked_login = PropertyMock() mocked_login.side_effect = github.BadCredentialsException( 401, 'dummy data') type(patched_get_user.return_value).login = mocked_login self.assertFalse(self.backend.are_creds_valid())
def test_githuborg_initautherror(githuborg_fixture): """ Test initializing GitHub API with failed authentication """ githuborg_mock, cred_mock, _ = githuborg_fixture cred_mock.return_value.load.return_value = ('user', 'pass') githuborg_mock.side_effect = github.BadCredentialsException('', '') with pytest.raises(ValueError): GitHubOrg('org', auth=True) cred_mock.assert_called_once_with('github') cred_mock.return_value.load.assert_called_once_with() cred_mock.return_value.clean.assert_called_once_with()
def __init__(self, username, password): incorrectPassword = (password != MockPyGithub.expectedPassword) incorrectUsername = (username != MockPyGithub.expectedUsername) if incorrectPassword or incorrectUsername: status = "status" data = "data" raise PyGithub.BadCredentialsException(status, data) MockPyGithub.username = username MockPyGithub.password = password
def test_get_profile_raises_error_on_bad_credentials(self): client = GithubClient() error = github.BadCredentialsException(None, None) with ExitStack() as stack: context_managers = ( mock.patch.object(client.client, 'get_user', side_effect=error), mock.patch.object(client, '_get_user_data', return_value={}), mock.patch.object(client, '_get_repository_data', return_value={}), ) for context_manager in context_managers: stack.enter_context(context_manager) with self.assertRaises(InvalidCredentialsError) as cm: client.get_profile('foobar') self.assertEqual(str(cm.exception), 'Cannot authenticate with given credentials')
def get_access_token(self, installation_id, user_id=None): """ Get an access token for the given installation id. POSTs https://api.github.com/installations/<installation_id>/access_tokens :param user_id: int :param installation_id: int :return: :class:`github.InstallationAuthorization.InstallationAuthorization` """ body = {} if user_id: body = {"user_id": user_id} response = requests.post( f"{self.__github_url}/installations/{installation_id}/access_tokens", headers={ "Authorization": "Bearer {}".format(self.create_jwt()), "Accept": github.Consts.mediaTypeIntegrationPreview, "User-Agent": "PyGithub/Python" }, json=body ) if response.status_code == 201: return github.InstallationAuthorization.InstallationAuthorization( requester=None, # not required, this is a NonCompletableGithubObject headers={}, # not required, this is a NonCompletableGithubObject attributes=response.json(), completed=True ) elif response.status_code == 403: raise github.BadCredentialsException( status=response.status_code, data=response.text ) elif response.status_code == 404: raise github.UnknownObjectException( status=response.status_code, data=response.text ) raise github.GithubException( status=response.status_code, data=response.text )
def exception_side_effect(_): raise github.BadCredentialsException('test', 'test')
def _gen_github_ses(github_login, github_passwd): """Generate viable Github sessions The idea is that we keep trying "new" ways to authenticate until we either exhaust or external loop stops asking for more Parameters ---------- github_login: github_passwd: Yields ------- Github, credential credential might be None if there is no credential associated as when we consider tokens from the config (instead of credentials store) """ if github_login == 'disabledloginfortesting': raise gh.BadCredentialsException(403, 'no login specified') # see if we have tokens - might be many. Doesn't cost us much so get at once all_tokens = tokens = unique( assure_list(cfg.get(CONFIG_HUB_TOKEN_FIELD, None)), reverse=True ) if not (github_login and github_passwd): # we don't have both # Check the tokens. If login is provided, only the token(s) for the # login are considered. We consider oauth tokens as stored/used by # https://github.com/sociomantic/git-hub if github_login and tokens: # Take only the tokens which are Ok and correspond to that login tokens = _get_tokens_for_login(github_login, tokens) for token in tokens: try: yield(gh.Github(token), None) except gh.BadCredentialsException as exc: lgr.debug("Failed to obtain Github session for token %s", _token_str(token)) # We got here so time to try credentials # if login and passwd were provided - try that one first try_creds = github_login and github_passwd try_login = bool(github_login) while True: if try_creds: # So we do not store them into cred store and thus do not need to # remove cred = None ses = gh.Github(github_login, password=github_passwd) user_name = github_login try_creds = None else: # make it per user if github_login was provided. People might want # to use different credentials etc cred = _get_github_cred(github_login) # if github_login was provided, we should first try it as is, # and only ask for password if not cred.is_known: creds = {'user': github_login} if try_login else {} cred.enter_new(**creds) try_login = None creds = cred() user_name = creds['user'] ses = gh.Github(user_name, password=creds['password']) # Get user and list its authorizations to verify that we do # not need 2FA user = ses.get_user() try: user_name_ = user.name # should trigger need for 2FA # authorizations = list(user.get_authorizations()) yield ses, cred except gh.BadCredentialsException as exc: lgr.error("Bad Github credentials") except (gh.TwoFactorException, gh.GithubException) as exc: # With github 1.43.5, in comparison to 1.40 we get a "regular" # GithubException for some reason, yet to check/report upstream # so we will just check for the expected in such cases messages if not ( isinstance(exc, gh.GithubException) and getattr(exc, 'data', {}).get('message', '').startswith( 'Must specify two-factor authentication OTP code') ): raise # 2FA - we need to interact! if not ui.is_interactive: # Or should we just allow to pass raise RuntimeError( "Cannot proceed with 2FA for Github - UI is not interactive. " "Please 'manually' establish token based authentication " "with Github and specify it in %s config" % CONFIG_HUB_TOKEN_FIELD ) if not ui.yesno( title="GitHub credentials - %s uses 2FA" % user_name, text="Generate a GitHub token to proceed? " "If you already have a token for the account, " "just say 'no' now and specify it in config (%s), " "otherwise say 'yes' " % (CONFIG_HUB_TOKEN_FIELD,) ): return token = _get_2fa_token(user) yield gh.Github(token), None # None for cred so does not get killed # if we are getting here, it means we are asked for more and thus # aforementioned one didn't work out :-/ if ui.is_interactive: if cred is not None: if ui.yesno( title="GitHub credentials", text="Do you want to try (re)entering GitHub credentials?" ): cred.enter_new() else: break else: # Nothing we could do lgr.debug( "UI is not interactive - we cannot query for more credentials" ) break
def _make_github_repo(github_login, entity, reponame, *args): if entity == 'entity1': raise gh.BadCredentialsException("very bad status", "some data") return reponame
def _make_github_repo(github_login, entity, reponame, *args): # Always throw an exception raise gh.BadCredentialsException("very bad status", "some data")
def test_githuborg_initerror(githuborg_fixture): """ Test initializing GitHub API failed """ githuborg_mock, _, _ = githuborg_fixture githuborg_mock.side_effect = github.BadCredentialsException('', '') with pytest.raises(ValueError): GitHubOrg('org', auth=False)
def _gen_github_ses(github_login): """Generate viable Github sessions The idea is that we keep trying "new" ways to authenticate until we either exhaust or external loop stops asking for more Parameters ---------- github_login: Yields ------- Github, token_str token_str is a shortened token string, so we do not reveal secret in full """ if github_login == 'disabledloginfortesting': raise gh.BadCredentialsException(403, 'no login specified') # see if we have tokens - might be many. Doesn't cost us much so get at once tokens = unique(ensure_list(cfg.get(CONFIG_HUB_TOKEN_FIELD, None)), reverse=True) # Check the tokens. If login is provided, only the token(s) for the # login are considered. We consider oauth tokens as stored/used by # https://github.com/sociomantic/git-hub if github_login and tokens: # Take only the tokens which are Ok and correspond to that login tokens = _get_tokens_for_login(github_login, tokens) for token in tokens: try: yield gh.Github(token), _token_str(token) except gh.BadCredentialsException as exc: lgr.debug("Failed to obtain Github session for token %s: %s", _token_str(token), exc_str(exc)) # We got here so time to get/store token from credential store cred = _get_github_cred(github_login) while True: token = cred()['token'] try: # ??? there was a comment # None for cred so does not get killed # while returning None as cred. Effect was not fully investigated from changing to return _token_str yield gh.Github(token), _token_str(token) except gh.BadCredentialsException as exc: lgr.debug("Failed to obtain Github session for token %s: %s", _token_str(token), exc_str(exc)) # if we are getting here, it means we are asked for more and thus # aforementioned one didn't work out :-/ if ui.is_interactive: if cred is not None: if ui.yesno( title="GitHub credentials", text= "Do you want to try (re)entering GitHub personal access token?" ): cred.enter_new() else: break else: # Nothing we could do lgr.warning( "UI is not interactive - we cannot query for more credentials") break