-
-
Save xuwei-k/63fc4d645237de9b74e67d39827ac63b to your computer and use it in GitHub Desktop.
Python script to find ENV_VAR keys on your travis projects
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
import argparse | |
import os | |
from math import ceil | |
from typing import List | |
try: | |
import requests | |
from requests import HTTPError | |
except ImportError: | |
print("This script uses the `requests` package") | |
print( | |
"To use it, follow https://docs.python-requests.org/en/latest/user/install/#install" | |
) | |
exit(1) | |
# ARGPARSE | |
parser = argparse.ArgumentParser( | |
description="Find TravisCI repos affected by their Sept 2021 security incident" | |
) | |
parser.add_argument( | |
"organization", help="The GitHub organization that owns the repos, like 'zapier'" | |
) | |
parser.add_argument( | |
"--travis-token", | |
help="A valid TravisCI token. Found at https://app.travis-ci.com/account/preferences. Can also be supplied in the environment as $TRAVIS_TOKEN.", | |
) | |
args = parser.parse_args() | |
# STORE ARGS | |
org = args.organization | |
token = args.travis_token or os.environ.get("TRAVIS_TOKEN") | |
if token is None: | |
raise ValueError("Missing TravisCI token. Either pass to script or set in env") | |
req_headers = {"authorization": f"token {token}", "Travis-API-Version": "3"} | |
# FUNCS | |
def make_request(url: str, params=None): | |
response = requests.get(url=url, params=params, headers=req_headers) | |
try: | |
response.raise_for_status() | |
except HTTPError: | |
if response.status_code != 403: | |
print(f'Got error: {response.json()["error_message"]}\n') | |
raise | |
return response.json() | |
def get_repos_by_page(): | |
params = {"private": "false", "sort_by": "default_branch.last_build"} | |
page = make_request(f"https://api.travis-ci.com/owner/{org}/repos", params=params) | |
print(f"Found {ceil(page['@pagination']['count'] / 100)} pages!\n") | |
# special case because we'll always do at least 1 page | |
print(f"Checking page 1...") | |
yield page["repositories"] | |
offset = 100 | |
while not page["@pagination"]["is_last"]: | |
print(f"Checking page {offset // 100 + 1}...") | |
page = make_request( | |
f"https://api.travis-ci.com/owner/{org}/repos", | |
params={**params, "offset": offset}, | |
) | |
yield page["repositories"] | |
offset += 100 | |
def get_vars_for_repo(repo_id: int) -> List[str]: | |
response = make_request(f"https://api.travis-ci.com/repo/github/{repo_id}/env_vars") | |
return [e["name"] for e in response["env_vars"]] | |
# MAIN | |
print( | |
f'Using TravisCI API to find public CI projects with environment variables in the "{org}" organization\n' | |
) | |
result = [] | |
for page in get_repos_by_page(): | |
for repo in page: | |
var_names = get_vars_for_repo(repo["id"]) | |
if var_names: | |
result.append( | |
"\n".join([f'- {repo["name"]}', *[f" - {v}" for v in var_names]]) | |
) | |
print(f"\n\nFound {len(result)} affected repos:\n") | |
print("\n\n".join(result)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment