-
-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds github client and PAT inspection (#138)
* Adds github client and PAT inspection * CI, Python version fixes Consolidate exceptions Signed-off-by: Caroline Russell <[email protected]> Output exception Signed-off-by: Caroline Russell <[email protected]> Handle GitHubException Signed-off-by: Caroline Russell <[email protected]> Don't fail-fast version_tests2 Signed-off-by: Caroline Russell <[email protected]> Fix type hints, unnecessary test runs Signed-off-by: Caroline Russell <[email protected]> * Addressing PR concerns * Adds 3.12 tests (#137) * Adds 3.12 tests Signed-off-by: Prabhu Subramanian <[email protected]> * Adds 3.12 tests Signed-off-by: Prabhu Subramanian <[email protected]> --------- Signed-off-by: Prabhu Subramanian <[email protected]> * Update to work with GitHub Actions tokens --------- Signed-off-by: Caroline Russell <[email protected]> Signed-off-by: Prabhu Subramanian <[email protected]> Co-authored-by: Tim Messing <[email protected]> Co-authored-by: Caroline Russell <[email protected]> Co-authored-by: prabhu <[email protected]>
- Loading branch information
1 parent
4910126
commit 54dd761
Showing
9 changed files
with
220 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
from github import Github, Auth | ||
from depscan.lib import config | ||
import httpx | ||
|
||
|
||
class GitHub: | ||
# The GitHub instance object from the PyGithub library | ||
github = None | ||
github_token = None | ||
|
||
|
||
def __init__(self, github_token: str) -> None: | ||
self.github = Github(auth=Auth.Token(github_token)) | ||
self.github_token = github_token | ||
|
||
|
||
def can_authenticate(self) -> bool: | ||
""" | ||
Calls the GitHub API to determine if the token is valid | ||
:return: Flag indicating whether authentication was successful or not | ||
""" | ||
headers = {"Authorization": f"token {self.github_token}"} | ||
|
||
response = httpx.get( | ||
url='https://api.github.com/', | ||
headers=headers, | ||
follow_redirects=True, | ||
timeout=config.request_timeout_sec | ||
) | ||
|
||
if response.status_code == 401: | ||
return False | ||
else: | ||
return True | ||
|
||
|
||
def get_token_scopes(self) -> list: | ||
""" | ||
Provides the scopes associated to the access token provided in the environment variable | ||
Only classic personal access tokens will result in scopes returned from the GitHub API | ||
:return: List of token scopes | ||
""" | ||
headers = {"Authorization": f"token {self.github_token}"} | ||
|
||
response = httpx.get( | ||
url='https://api.github.com/', | ||
headers=headers, | ||
follow_redirects=True, | ||
timeout=config.request_timeout_sec | ||
) | ||
|
||
oauth_scopes = response.headers.get('x-oauth-scopes') | ||
|
||
if not oauth_scopes is None: | ||
if oauth_scopes == '': | ||
return None | ||
else: | ||
return oauth_scopes.split(', ') | ||
|
||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from depscan.lib import github | ||
import httpretty | ||
|
||
|
||
url = 'https://api.github.com/' | ||
|
||
|
||
def test_can_authenticate_success(): | ||
httpretty.enable() | ||
httpretty.reset() | ||
|
||
headers = { | ||
'content-type': 'application/json', | ||
'X-OAuth-Scopes': 'admin:org, admin:repo_hook, repo, user', | ||
'X-Accepted-OAuth-Scopes': 'repo' | ||
} | ||
|
||
httpretty.register_uri( | ||
method=httpretty.GET, | ||
uri=url, | ||
adding_headers=headers | ||
) | ||
|
||
github_client = github.GitHub('test-token') | ||
result = github_client.can_authenticate() | ||
|
||
httpretty.disable() | ||
|
||
assert result == True | ||
|
||
|
||
def test_can_authenticate_unauthentiated(): | ||
httpretty.enable() | ||
httpretty.reset() | ||
|
||
headers = { | ||
'content-type': 'application/json' | ||
} | ||
|
||
httpretty.register_uri( | ||
method=httpretty.GET, | ||
uri=url, | ||
body='{"message":"Bad credentials"}', | ||
adding_headers=headers, | ||
status=401 | ||
) | ||
|
||
github_client = github.GitHub('test-token') | ||
result = github_client.can_authenticate() | ||
|
||
httpretty.disable() | ||
|
||
assert result == False | ||
|
||
|
||
def test_get_token_scopes_success(): | ||
httpretty.enable() | ||
httpretty.reset() | ||
|
||
headers = { | ||
'content-type': 'application/json', | ||
'X-OAuth-Scopes': 'admin:org, admin:repo_hook, repo, user', | ||
'X-Accepted-OAuth-Scopes': 'repo' | ||
} | ||
|
||
httpretty.register_uri( | ||
method=httpretty.GET, | ||
uri=url, | ||
adding_headers=headers | ||
) | ||
|
||
github_client = github.GitHub('test-token') | ||
result = github_client.get_token_scopes() | ||
|
||
httpretty.disable() | ||
|
||
assert len(result) == 4 and result.index('admin:org') >= 0 and result.index('admin:repo_hook') >= 0 and result.index('repo') >= 0 and result.index('user') >= 0 | ||
|
||
|
||
def test_get_token_scopes_none(): | ||
httpretty.enable() | ||
httpretty.reset() | ||
|
||
headers = { | ||
'content-type': 'application/json', | ||
} | ||
|
||
httpretty.register_uri( | ||
method=httpretty.GET, | ||
uri=url, | ||
adding_headers=headers | ||
) | ||
|
||
github_client = github.GitHub('test-token') | ||
result = github_client.get_token_scopes() | ||
|
||
httpretty.disable() | ||
|
||
assert result is None | ||
|
||
|
||
def test_get_token_scopes_empty(): | ||
httpretty.enable() | ||
httpretty.reset() | ||
|
||
headers = { | ||
'content-type': 'application/json', | ||
'x-oauth-scopes': '' | ||
} | ||
|
||
httpretty.register_uri( | ||
method=httpretty.GET, | ||
uri=url, | ||
adding_headers=headers | ||
) | ||
|
||
github_client = github.GitHub('test-token') | ||
result = github_client.get_token_scopes() | ||
|
||
httpretty.disable() | ||
|
||
assert result is None |