Skip to content

Commit

Permalink
Develop (#5)
Browse files Browse the repository at this point in the history
* Bump requests from 2.26.0 to 2.31.0

Bumps [requests](https://github.com/psf/requests) from 2.26.0 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](psf/requests@v2.26.0...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <[email protected]>

* Create dependency-review.yml

* make sure code scanning tools reported are unique

* code cleanup

* add in code alert counts. parse codeowners content if found

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
austimkelly and dependabot[bot] authored Nov 21, 2023
1 parent 296af0d commit 5e40f06
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 40 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/dependency-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Dependency Review Action
#
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
#
# Source repository: https://github.com/actions/dependency-review-action
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
name: 'Dependency Review'
on: [pull_request]

permissions:
contents: read

jobs:
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Dependency Review'
uses: actions/dependency-review-action@v3
149 changes: 110 additions & 39 deletions ghas-scan.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import csv
import requests
import os
import base64
import re

# Set the GitHub owner type, owner name, and personal access token
owner_type = 'user' # Change to 'org' if needed
Expand Down Expand Up @@ -66,45 +68,98 @@ def get_dependabot_alerts(owner, repo_name, headers):
num_low_dep_alerts
)

# API Ref: https://docs.github.com/en/rest/code-scanning/code-scanning
def get_code_scanning_tool_names(owner, repo_name, headers):
url = "https://api.github.com/repos/" + owner + "/" + repo_name + "/code-scanning/analyses"
url = f'https://api.github.com/repos/{owner}/{repo_name}/code-scanning/analyses'
#print("Request URL:", url)

try:
response = requests.get(url, headers=headers)
if response.status_code == 404:
return "None"
response.raise_for_status() # Raises a HTTPError if the status is 4xx, 5xx

data = response.json()

if data:
return data[0]['tool']['name']
# Extract unique tools from the analyses
tools = list(set(analysis['tool']['name'] for analysis in data))
return ', '.join(tools)
else:
return "No data received from the server"
except requests.exceptions.HTTPError as http_err:
return f"HTTPError: {http_err}"
if response.status_code == 404:
return "None"
else:
return f"HTTPError: {http_err}"
except Exception as err:
return f"Error occurred: {err}"

def is_secrets_scanning_enabled(owner, repo_name, headers):
secrets_scanning_url = f'https://api.github.com/repos/{owner}/{repo_name}/secret-scanning/alerts'
response = requests.get(secrets_scanning_url, headers=headers)
return len(response.json()) > 0
# API Ref: https://docs.github.com/en/rest/reference/code-scanning#list-code-scanning-alerts-for-a-repository
def get_code_scanning_alert_counts(owner, repo_name, headers):
# Get the code scanning alerts for the repository
url = f'https://api.github.com/repos/{owner}/{repo_name}/code-scanning/alerts'
response = requests.get(url, headers=headers)

code_scanning_critical_alert_count = 0
code_scanning_high_alert_count = 0
code_scanning_medium_alert_count = 0
code_scanning_low_alert_count = 0
code_scanning_warning_alert_count = 0
code_scanning_note_alert_count = 0
code_scanning_error_alert_count = 0

if response.status_code == 200:
alerts_data = response.json()

# Filter open code scanning alerts
open_alerts = [alert for alert in alerts_data if alert['state'] == 'open']

# Count alerts based on severity
for alert in open_alerts:
severity = alert['rule']['severity']
if severity == 'critical':
code_scanning_critical_alert_count += 1
elif severity == 'high':
code_scanning_high_alert_count += 1
elif severity == 'medium':
code_scanning_medium_alert_count += 1
elif severity == 'low':
code_scanning_low_alert_count += 1
elif severity == 'warning':
code_scanning_warning_alert_count += 1
elif severity == 'note':
code_scanning_note_alert_count += 1
elif severity == 'error':
code_scanning_error_alert_count += 1

return (
code_scanning_critical_alert_count,
code_scanning_high_alert_count,
code_scanning_medium_alert_count,
code_scanning_low_alert_count,
code_scanning_warning_alert_count,
code_scanning_note_alert_count,
code_scanning_error_alert_count
)

def get_codeowners(owner, repo_name, headers):
codeowners_locations = [
f'https://api.github.com/repos/{owner}/{repo_name}/CODEOWNERS',
f'https://api.github.com/repos/{owner}/{repo_name}/.github/CODEOWNERS',
f'https://api.github.com/repos/{owner}/{repo_name}/docs/CODEOWNERS'
f'https://api.github.com/repos/{owner}/{repo_name}/contents/CODEOWNERS',
f'https://api.github.com/repos/{owner}/{repo_name}/contents/.github/CODEOWNERS',
f'https://api.github.com/repos/{owner}/{repo_name}/contents/docs/CODEOWNERS'
]

for location in codeowners_locations:
codeowners_response = requests.get(location, headers=headers)

#print(f"Location: {location}, Status Code: {codeowners_response.status_code}")

if codeowners_response.status_code == 200:
codeowners = codeowners_response.text
return codeowners
codeowners_content = codeowners_response.json().get('content')
if codeowners_content is not None:
codeowners = base64.b64decode(codeowners_content).decode('utf-8')

# Remove comments from CODEOWNERS
codeowners_lines = [line for line in codeowners.split('\n') if not line.strip().startswith('#')]

return '\n'.join(codeowners_lines)

return "Not found"

Expand Down Expand Up @@ -133,11 +188,26 @@ def get_repo_details(owner, repo_name, headers):
is_archived = repo_info['archived']

# Check if secrets scanning is enabled
secrets_scanning_enabled = is_secrets_scanning_enabled(owner, repo_name, headers)

security_and_analysis = repo_info.get('security_and_analysis', {})
#advanced_security = security_and_analysis.get('advanced_security', {})
secret_scanning = security_and_analysis.get('secret_scanning', {})
secret_scanning_push_protection = security_and_analysis.get('secret_scanning_push_protection', {})

# even though scheam docs say this exists, it doesn't
# https://docs.github.com/en/rest/repos/repos?apiVersion=2022-11-28#list-repositories-for-a-user
# security_and_analysis_enabled = advanced_security.get('status') == 'enabled' if advanced_security else False
secret_scanning_enabled = secret_scanning.get('status') == 'enabled' if secret_scanning else False
secret_scanning_push_protection_enabled = secret_scanning_push_protection.get('status') == 'enabled' if secret_scanning_push_protection else False

# Get names of code scanners
code_scanners_enabled = get_code_scanning_tool_names(owner, repo_name, headers)

code_scanning_critical_alert_count,code_scanning_high_alert_count,code_scanning_medium_alert_count,code_scanning_low_alert_count,code_scanning_warning_alert_count,code_scanning_note_alert_count,code_scanning_error_alert_count = get_code_scanning_alert_counts(owner, repo_name, headers)

security_and_analysis_enabled = False
if code_scanners_enabled != "None":
security_and_analysis_enabled = True

# Check the number of Dependabot alerts
dependabot_enabled, open_alerts_count, num_critical_dep_alerts, num_high_dep_alerts, num_medium_dep_alerts, num_low_dep_alerts = get_dependabot_alerts(owner, repo_name, headers)

Expand All @@ -149,26 +219,17 @@ def get_repo_details(owner, repo_name, headers):
'is_fork': is_fork,
'is_private': is_private,
'is_archived': is_archived,
'secrets_scanning_enabled': secrets_scanning_enabled,
'code_scanners_enabled': code_scanners_enabled,
'dependabot_enabled': dependabot_enabled,
'dependabot_open_alerts_count': open_alerts_count,
'num_critical_dep_alerts': num_critical_dep_alerts,
'num_high_dep_alerts': num_high_dep_alerts,
'num_medium_dep_alerts': num_medium_dep_alerts,
'num_low_dep_alerts': num_low_dep_alerts
# Add other details here
}
return {
'repo_name': repo_info['name'],
'codeowners': codeowners,
'last_commit_date': last_commit_date,
'first_commit_date': first_commit_date,
'is_fork': is_fork,
'is_private': is_private,
'is_archived': is_archived,
'secrets_scanning_enabled': secrets_scanning_enabled,
'security_and_analysis_enabled': security_and_analysis_enabled,
'secret_scanning_enabled': secret_scanning_enabled,
'secret_scanning_push_protection_enabled': secret_scanning_push_protection_enabled,
'code_scanners_enabled': code_scanners_enabled,
'code_scanning_critical_alert_count': code_scanning_critical_alert_count,
'code_scanning_high_alert_count': code_scanning_high_alert_count,
'code_scanning_medium_alert_count': code_scanning_medium_alert_count,
'code_scanning_low_alert_count': code_scanning_low_alert_count,
'code_scanning_warning_alert_count': code_scanning_warning_alert_count,
'code_scanning_note_alert_count': code_scanning_note_alert_count,
'code_scanning_error_alert_count': code_scanning_error_alert_count,
'dependabot_enabled': dependabot_enabled,
'dependabot_open_alerts_count': open_alerts_count,
'num_critical_dep_alerts': num_critical_dep_alerts,
Expand All @@ -177,6 +238,7 @@ def get_repo_details(owner, repo_name, headers):
'num_low_dep_alerts': num_low_dep_alerts
# Add other details here
}


def get_repos(owner, headers, owner_type):
if owner_type == 'user':
Expand Down Expand Up @@ -213,8 +275,17 @@ def get_repos(owner, headers, owner_type):
'is_fork',
'is_private',
'is_archived',
'secrets_scanning_enabled',
'security_and_analysis_enabled',
'secret_scanning_enabled',
'secret_scanning_push_protection_enabled',
'code_scanners_enabled',
'code_scanning_critical_alert_count',
'code_scanning_high_alert_count',
'code_scanning_medium_alert_count',
'code_scanning_low_alert_count',
'code_scanning_warning_alert_count',
'code_scanning_note_alert_count',
'code_scanning_error_alert_count',
'dependabot_enabled',
'dependabot_open_alerts_count',
'num_critical_dep_alerts',
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
requests==2.26.0
requests==2.31.0

0 comments on commit 5e40f06

Please sign in to comment.