From 1b19b598cd78856afbd93115dae9a939719b6b53 Mon Sep 17 00:00:00 2001 From: raulsh Date: Tue, 15 Mar 2022 01:53:58 -0300 Subject: [PATCH 1/3] change auth from access token to github app --- setup.py | 3 ++- tap_github/__init__.py | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 4b191385..1ada2c45 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,8 @@ install_requires=[ 'singer-python==5.12.1', 'requests==2.20.0', - 'backoff==1.8.0' + 'backoff==1.8.0', + 'PyJWT==1.7.1' ], extras_require={ 'dev': [ diff --git a/tap_github/__init__.py b/tap_github/__init__.py index 5c2d768a..f94581b8 100644 --- a/tap_github/__init__.py +++ b/tap_github/__init__.py @@ -5,6 +5,7 @@ import requests import backoff import singer +import jwt from singer import (bookmarks, metrics, metadata) from simplejson import JSONDecodeError @@ -15,7 +16,7 @@ # set default timeout of 300 seconds REQUEST_TIMEOUT = 300 -REQUIRED_CONFIG_KEYS = ['start_date', 'access_token', 'repository'] +REQUIRED_CONFIG_KEYS = ['start_date', 'repository', 'github_app_id', 'github_installation_id', 'github_private_key'] KEY_PROPERTIES = { 'commits': ['sha'], @@ -1172,6 +1173,36 @@ def do_sync(config, state, catalog): singer.write_state(state) +def generate_jwt_token(github_app_id, github_private_key, expiration_time = 600, algorithm = 'RS256'): + actual_time = int(time.time()) + + payload = { + 'iat': actual_time, + 'exp': actual_time + expiration_time, + 'iss': github_app_id + } + + return jwt.encode(payload, github_private_key, algorithm=algorithm).decode('utf-8') + +def generate_access_token(config): + jwt_token = generate_jwt_token( + config['github_app_id'], + config['github_private_key'] + ) + + headers = { + "Authorization": "Bearer {}".format(jwt_token), + "Accept": "application/vnd.github.machine-man-preview+json" + } + + url = 'https://api.github.com/app/installations/{}/access_tokens'.format(config['github_installation_id']) + resp = requests.post(url, headers = headers) + + if resp.status_code != 201: + raise_for_error(resp, url) + + return resp.json()['token'] + @singer.utils.handle_top_exception(logger) def main(): args = singer.utils.parse_args(REQUIRED_CONFIG_KEYS) @@ -1183,6 +1214,9 @@ def main(): global MAX_SLEEP_SECONDS #pylint: disable=global-statement MAX_SLEEP_SECONDS = config_max_sleep if config_max_sleep else DEFAULT_SLEEP_SECONDS + # set access token from github app + args.config['access_token'] = generate_access_token(args.config) + if args.discover: do_discover(args.config) else: From 4a949a96366d103dd7249eca3432bfbc32ef408d Mon Sep 17 00:00:00 2001 From: raulsh Date: Tue, 15 Mar 2022 02:01:20 -0300 Subject: [PATCH 2/3] add cryptography dependency to setup.py --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 1ada2c45..fd5bcecc 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,8 @@ 'singer-python==5.12.1', 'requests==2.20.0', 'backoff==1.8.0', - 'PyJWT==1.7.1' + 'PyJWT==1.7.1', + 'cryptography' ], extras_require={ 'dev': [ From ecde3d3e7a5093189215584898a587531d6a0ba2 Mon Sep 17 00:00:00 2001 From: raulsh Date: Tue, 15 Mar 2022 02:26:27 -0300 Subject: [PATCH 3/3] fix dependency and token generation --- setup.py | 3 +-- tap_github/__init__.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index fd5bcecc..59ecd4d5 100644 --- a/setup.py +++ b/setup.py @@ -13,8 +13,7 @@ 'singer-python==5.12.1', 'requests==2.20.0', 'backoff==1.8.0', - 'PyJWT==1.7.1', - 'cryptography' + 'PyJWT[crypto]==2.3.0' ], extras_require={ 'dev': [ diff --git a/tap_github/__init__.py b/tap_github/__init__.py index f94581b8..e9050f08 100644 --- a/tap_github/__init__.py +++ b/tap_github/__init__.py @@ -1182,7 +1182,7 @@ def generate_jwt_token(github_app_id, github_private_key, expiration_time = 600, 'iss': github_app_id } - return jwt.encode(payload, github_private_key, algorithm=algorithm).decode('utf-8') + return jwt.encode(payload, github_private_key, algorithm=algorithm) def generate_access_token(config): jwt_token = generate_jwt_token(