Update octosuite

This commit is contained in:
Richard Mwewa
2023-02-25 02:59:46 +02:00
committed by GitHub
parent 04f3bd89cf
commit 774c8d19a8
5 changed files with 68 additions and 68 deletions

View File

@@ -25,14 +25,14 @@ def usage():
octosuite --method user_repos --username <username>
Get Organi[sz]ation Profile Info
Get Organisation Profile Info
-----------------------------
octosuite --method org_profile --organization <organization_name>
octosuite --method org_profile --organisation <organisation_name>
Get Organi[sz]ation Repos
-----------------------------
octosuite --method org_repos --organization <organization_name>
octosuite --method org_repos --organisation <organisation_name>
Get Repo Profile Info
@@ -134,7 +134,7 @@ def create_parser():
'clear_logs', 'view_csv', 'read_csv', 'delete_csv', 'clear_csv', 'about', 'author'])
parser.add_argument('-u', '--username', help='username')
parser.add_argument('-uB', '--username_b', help='username_B (used with user_follows)')
parser.add_argument('-o', '--organization', '--organisation', help='organi[sz]ation name')
parser.add_argument('-o', '--organisation', '--organization', help='organisation name')
parser.add_argument('-r', '--repository', help='repository name')
parser.add_argument('-p', '--path_name', help='path name (used with repo_path_contents)')
parser.add_argument('-q', '--query', help='query (used with search methods)')

View File

@@ -11,14 +11,14 @@ from octosuite.message_prefixes import PROMPT, WARNING, POSITIVE, NEGATIVE, INFO
def log_org_profile(response):
org_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Email', 'About', 'Location', 'Blog',
'Followers', 'Following', 'Twitter handle', 'Gists', 'Repositories', 'Account type',
'Is verified?', 'Has organization projects?', 'Has repository projects?', 'Created at',
'Is verified?', 'Has organisation projects?', 'Has repository projects?', 'Created at',
'Updated at']
org_profile_row = [response.json()['avatar_url'], response.json()['name'], response.json()['login'],
response.json()['id'], response.json()['node_id'], response.json()['email'],
response.json()['description'], response.json()['location'], response.json()['blog'],
response.json()['followers'], response.json()['following'], response.json()['twitter_username'],
response.json()['public_gists'], response.json()['public_repos'], response.json()['type'],
response.json()['is_verified'], response.json()['has_organization_projects'],
response.json()['is_verified'], response.json()['has_organisation_projects'],
response.json()['has_repository_projects'], response.json()['created_at'],
response.json()['updated_at']]
@@ -34,7 +34,7 @@ def log_org_profile(response):
# Creating a .csv file of a user' profile
def log_user_profile(response):
user_profile_fields = ['Profile photo', 'Name', 'Username', 'ID', 'Node ID', 'Bio', 'Blog', 'Location', 'Followers',
'Following', 'Twitter handle', 'Gists', 'Repositories', 'Organization', 'Is hireable?',
'Following', 'Twitter handle', 'Gists', 'Repositories', 'organisation', 'Is hireable?',
'Is site admin?', 'Joined at', 'Updated at']
user_profile_row = [response.json()['avatar_url'], response.json()['name'], response.json()['login'],
response.json()['id'], response.json()['node_id'], response.json()['bio'],
@@ -184,12 +184,12 @@ def log_repo_contributors(contributor, repo_name):
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
# Create .csv for organization' events
def log_repo_events(event, organization):
# Create .csv for organisation' events
def log_repo_events(event, organisation):
org_event_fields = ['ID', 'Type', 'Created at', 'Payload']
org_event_row = [event['id'], event['type'], event['created_at'], event['payload']]
with open(os.path.join("output", f"{organization}_event_{event['id']}.csv"), 'w') as file:
with open(os.path.join("output", f"{organisation}_event_{event['id']}.csv"), 'w') as file:
write_csv = csv.writer(file)
write_csv.writerow(org_event_fields)
write_csv.writerow(org_event_row)
@@ -198,8 +198,8 @@ def log_repo_events(event, organization):
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
# Create .csv for organization' repositories
def log_org_repos(repository, organization):
# Create .csv for organisation' repositories
def log_org_repos(repository, organisation):
org_repo_fields = ['Name', 'ID', 'About', 'Forks', 'Stars', 'Watchers', 'License', 'Branch', 'Visibility',
'Language(s)', 'Open issues', 'Topics', 'Homepage', 'Clone URL', 'SSH URL', 'Is fork?',
'Is forkable?', 'Is private?', 'Is archived?', 'Is template?', 'Has wiki?', 'Has pages?',
@@ -213,7 +213,7 @@ def log_org_repos(repository, organization):
repository['has_projects'], repository['has_issues'], repository['has_downloads'],
repository['pushed_at'], repository['created_at'], repository['updated_at']]
with open(os.path.join("output", f"{repository['name']}_repository_of_{organization}.csv"), 'w') as file:
with open(os.path.join("output", f"{repository['name']}_repository_of_{organisation}.csv"), 'w') as file:
write_csv = csv.writer(file)
write_csv.writerow(org_repo_fields)
write_csv.writerow(org_repo_row)
@@ -335,13 +335,13 @@ def log_user_subscriptions(repository, username):
xprint(f"{POSITIVE} {logged_to_csv.format(file.name)}")
# .csv for user organizations
def log_user_orgs(organization, username):
# .csv for user organisations
def log_user_orgs(organisation, username):
user_org_fields = ['Profile photo', 'Name', 'ID', 'Node ID', 'URL', 'About']
user_org_row = [organization['avatar_url'], organization['login'], organization['id'], organization['node_id'],
organization['url'], organization['description']]
user_org_row = [organisation['avatar_url'], organisation['login'], organisation['id'], organisation['node_id'],
organisation['url'], organisation['description']]
with open(os.path.join("output", f"{organization['login']}_{username}.csv"), 'w') as file:
with open(os.path.join("output", f"{organisation['login']}_{username}.csv"), 'w') as file:
write_csv = csv.writer(file)
write_csv.writerow(user_org_fields)
write_csv.writerow(user_org_row)

View File

@@ -70,7 +70,7 @@ def user_command():
user_cmd_table.add_row("email", "Return a target's email")
user_cmd_table.add_row("profile", "Get a target's profile info")
user_cmd_table.add_row("gists", "Return a users's gists")
user_cmd_table.add_row("orgs", "Return organizations that a target belongs to/owns")
user_cmd_table.add_row("orgs", "Return organisations that a target belongs to/owns")
user_cmd_table.add_row("repos", "Return a target's repositories")
user_cmd_table.add_row("events", "Return a target's events")
user_cmd_table.add_row("follows", "Check if user(A) follows user(B)")
@@ -87,13 +87,13 @@ def org_command():
org_cmd_table = Table(show_header=True, header_style=header_title)
org_cmd_table.add_column("Command", style="dim")
org_cmd_table.add_column("Description")
org_cmd_table.add_row("profile", "Get a target organization' profile info")
org_cmd_table.add_row("repos", "Return a target organization' repositories")
org_cmd_table.add_row("events", "Return a target organization' events")
org_cmd_table.add_row("member", "Check if a specified user is a public member of the target organization")
org_cmd_table.add_row("profile", "Get a target organisation' profile info")
org_cmd_table.add_row("repos", "Return a target organisation' repositories")
org_cmd_table.add_row("events", "Return a target organisation' events")
org_cmd_table.add_row("member", "Check if a specified user is a public member of the target organisation")
syntax = f"{green}org:<command>{reset}"
xprint(f"{usage_text.format(syntax, 'organization investigation(s)')}")
xprint(f"{usage_text.format(syntax, 'organisation investigation(s)')}")
xprint(org_cmd_table)
@@ -159,7 +159,7 @@ def help_command():
help_sub_cmd_table.add_column("Description")
help_sub_cmd_table.add_row("csv", "List all csv management commands")
help_sub_cmd_table.add_row("logs", "List all logs management commands")
help_sub_cmd_table.add_row("org", "List all organization investigation commands")
help_sub_cmd_table.add_row("org", "List all organisation investigation commands")
help_sub_cmd_table.add_row("user", "List all users investigation commands")
help_sub_cmd_table.add_row("repo", "List all repository investigation commands")
help_sub_cmd_table.add_row("search", "List all target discovery commands")

View File

@@ -14,7 +14,7 @@ file_downloading = "Downloading: {}"
file_downloaded = "Downloaded: downloads/{}"
info_not_found = "Information not found: {}, {}, {}"
user_not_found = "User not found: @{}"
org_not_found = "Organization not found: @{}"
org_not_found = "organisation not found: @{}"
repo_or_user_not_found = "Repository or User not found: {}, @{}"
prompt_log_csv = "Would you like to log this output to a .csv file?"
logged_to_csv = "Output logged: {}"

View File

@@ -202,7 +202,7 @@ def about():
about_text = f"""
OCTOSUITE © 2023 Richard Mwewa
An advanced and lightning fast framework for gathering open-source intelligence on GitHub users and organizations.
An advanced and lightning fast framework for gathering open-source intelligence on GitHub users and organisations.
Read the wiki: https://github.com/bellingcat/octosuite/wiki
GitHub REST API documentation: https://docs.github.com/rest
@@ -338,12 +338,12 @@ class Octosuite:
'sha': 'SHA',
'html_url': 'URL'}
# Organization attributes
# organisation attributes
self.org_attrs = ['avatar_url', 'login', 'id', 'node_id', 'email', 'description', 'blog', 'location',
'followers',
'following', 'twitter_username', 'public_gists', 'public_repos', 'type', 'is_verified',
'has_organization_projects', 'has_repository_projects', 'created_at', 'updated_at']
# Organization attribute dictionary
'has_organisation_projects', 'has_repository_projects', 'created_at', 'updated_at']
# organisation attribute dictionary
self.org_attr_dict = {'avatar_url': 'Profile Photo',
'login': 'Username',
'id': 'ID',
@@ -359,7 +359,7 @@ class Octosuite:
'public_repos': 'Repositories',
'type': 'Account type',
'is_verified': 'Is verified?',
'has_organization_projects': 'Has organization projects?',
'has_organisation_projects': 'Has organisation projects?',
'has_repository_projects': 'Has repository projects?',
'created_at': 'Created at',
'updated_at': 'Updated at'}
@@ -435,7 +435,7 @@ class Octosuite:
'twitter_username': 'Twitter Handle',
'public_gists': 'Gists (public)',
'public_repos': 'Repositories (public)',
'company': 'Organization',
'company': 'organisation',
'hireable': 'Is hireable?',
'site_admin': 'Is site admin?',
'created_at': 'Joined at',
@@ -519,7 +519,7 @@ class Octosuite:
'created_at': 'Created at',
'updated_at': 'Updated at'}
# User organizations attributes
# User organisations attributes
self.user_orgs_attrs = ['avatar_url', 'id', 'node_id', 'url', 'description']
self.user_orgs_attr_dict = {'avatar_url': 'Profile Photo',
'id': 'ID',
@@ -555,15 +555,15 @@ class Octosuite:
xprint(f"{username}: {email}")
break
# Fetching organization info
# Fetching organisation info
def org_profile(self):
if args.organization:
organization = args.organization
if args.organisation:
organisation = args.organisation
else:
organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
response = requests.get(f"{self.endpoint}/orgs/{organization}")
organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
response = requests.get(f"{self.endpoint}/orgs/{organisation}")
if response.status_code == 404:
xprint(f"{NEGATIVE} {org_not_found.format(organization)}")
xprint(f"{NEGATIVE} {org_not_found.format(organisation)}")
elif response.status_code == 200:
org_profile_tree = Tree("\n{response.json()['name']}")
for attr in self.org_attrs:
@@ -775,17 +775,17 @@ class Octosuite:
else:
xprint(response.json())
# Fetching organization repositories
# Fetching organisation repositories
def org_repos(self):
if args.organization and args.limit:
organization = args.organization
if args.organisation and args.limit:
organisation = args.organisation
limit = args.limit
else:
organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
limit = Prompt.ask(limit_output.format("organization repositories"))
response = requests.get(f"{self.endpoint}/orgs/{organization}/repos?per_page={limit}")
organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
limit = Prompt.ask(limit_output.format("organisation repositories"))
response = requests.get(f"{self.endpoint}/orgs/{organisation}/repos?per_page={limit}")
if response.status_code == 404:
xprint(f"{NEGATIVE} {org_not_found.format(organization)}")
xprint(f"{NEGATIVE} {org_not_found.format(organisation)}")
elif response.status_code == 200:
for repository in response.json():
repos_tree = Tree("\n" + repository['full_name'])
@@ -794,21 +794,21 @@ class Octosuite:
xprint(repos_tree)
if args.log_csv or Prompt.ask(f"{PROMPT} {prompt_log_csv}") == "yes":
log_org_repos(repository, organization)
log_org_repos(repository, organisation)
else:
xprint(response.json())
# organization events
# organisation events
def org_events(self):
if args.organization and args.limit:
organization = args.organization
if args.organisation and args.limit:
organisation = args.organisation
limit = args.limit
else:
organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
limit = Prompt.ask(limit_output.format("organization events"))
response = requests.get(f"{self.endpoint}/orgs/{organization}/events?per_page={limit}")
organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
limit = Prompt.ask(limit_output.format("organisation events"))
response = requests.get(f"{self.endpoint}/orgs/{organisation}/events?per_page={limit}")
if response.status_code == 404:
xprint(f"{NEGATIVE} {org_not_found.format(organization)}")
xprint(f"{NEGATIVE} {org_not_found.format(organisation)}")
elif response.status_code == 200:
for event in response.json():
events_tree = Tree("\n" + event['id'])
@@ -816,21 +816,21 @@ class Octosuite:
events_tree.add(f"Created at: {event['created_at']}")
xprint(events_tree)
xprint(event['payload'])
# log_org_events(event, organization)
# log_org_events(event, organisation)
else:
xprint(response.json())
# organization member
# organisation member
def org_member(self):
if args.organization and args.username:
organization = args.organization
if args.organisation and args.username:
organisation = args.organisation
username = args.username
else:
organization = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
organisation = Prompt.ask(f"{white}@{green}Organi[sz]ation{reset}")
username = Prompt.ask(f"{white}@{green}Username{reset}")
response = requests.get(f"{self.endpoint}/orgs/{organization}/public_members/{username}")
response = requests.get(f"{self.endpoint}/orgs/{organisation}/public_members/{username}")
if response.status_code == 204:
xprint(f"{POSITIVE} User ({username}) is a public member of the organization -> ({organization})")
xprint(f"{POSITIVE} User ({username}) is a public member of the organisation -> ({organisation})")
else:
xprint(f"{NEGATIVE} {response.json()['message']}")
@@ -882,28 +882,28 @@ class Octosuite:
else:
xprint(response.json())
# Fetching a list of organizations that a user owns or belongs to
# Fetching a list of organisations that a user owns or belongs to
def user_orgs(self):
if args.username and args.limit:
username = args.username
limit = args.limit
else:
username = Prompt.ask(f"{white}@{green}Username{reset}")
limit = Prompt.ask(limit_output.format("user organizations"))
limit = Prompt.ask(limit_output.format("user organisations"))
response = requests.get(f"{self.endpoint}/users/{username}/orgs?per_page={limit}")
if not response.json():
xprint(f"{NEGATIVE} User ({username}) does not (belong to/own) any organizations.")
xprint(f"{NEGATIVE} User ({username}) does not (belong to/own) any organisations.")
elif response.status_code == 404:
xprint(f"{NEGATIVE} {user_not_found.format(username)}")
elif response.status_code == 200:
for organization in response.json():
org_tree = Tree("\n" + organization['login'])
for organisation in response.json():
org_tree = Tree("\n" + organisation['login'])
for attr in self.user_orgs_attrs:
org_tree.add(f"{self.user_orgs_attr_dict[attr]}: {organization[attr]}")
org_tree.add(f"{self.user_orgs_attr_dict[attr]}: {organisation[attr]}")
xprint(org_tree)
if args.log_csv or Confirm.ask(f"\n{PROMPT} {prompt_log_csv}"):
log_user_orgs(organization, username)
log_user_orgs(organisation, username)
else:
xprint(response.json())