-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor top-level readme, add in starter code for alert updates API (#…
…17) * code and doc cleanup. make a demos table on the landing readme.md * progress on updating security alerts
- Loading branch information
1 parent
eff1901
commit 9dc2271
Showing
12 changed files
with
253 additions
and
73 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,77 +1,23 @@ | ||
# GHAS Scan | ||
# GHAS Utils | ||
|
||
This is a Python script that interacts with the GitHub API to fetch repository details and code scanning analysis information. | ||
Make sure the repository exists and your GitHub token has the necessary permissions to access it. | ||
# Utils | ||
|
||
## Prerequisites | ||
Here's a table with all the demo/utilities and what they do: | ||
|
||
- Python 3.6 or higher | ||
- `requests` library | ||
> NOTE: There are not meant to be production grade scripts. They are meant to be education and to help you understand some areas where you would want to use the GitHub API. | ||
## Installation | ||
| Demo name | Demo description | | ||
|-----------|-----------------| | ||
| [ghas-org-scan](./ghas-org-scan/) | This is a sort of compliance report that builds a table of settings and security alert volumes for all repositories in an organization. This is a great way to quickly spot out-of-compliance repositories where GitHub reporting may fall short. | | ||
| [ghas-settings](./ghas-settings/) | This is a simple demo to show you want GHAS settings you can read and write for an organization. GitHub does support https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository now, but this is good if you want to keep things programatically synchronized or have tons or orgs. | | ||
| [pull_all_org_security_alerts](./pull_all_org_security_alerts/) | This pulls all the dependabot, secret, and code scanning alerts into 3 CSV files for an organization. | | ||
| [pull_all_repo_security_alerts](./pull_all_repo_security_alerts/) | This just pulls security alerts and advisories for a repo. There's some extra documentation in there about the alert schemas and how to think about your security alert observability program. | | ||
| [sbom-visualizer](./sbom-visualizer/) | This is just a quick hack to see how to parse the SBOM export from GitHub. It's nothing special here. | | ||
| [secret-alert-pull](./secret-alert-pull/) | Pulls all secrets for an org. | | ||
| [update-security-alerts](./update-security-alerts/) | This demo show how to update security alerts. This can be useful when needing to bulk modify hundreds or thousands of security alerts. | | ||
|
||
1. Clone this repository: | ||
```bash | ||
git clone git@github.com:austimkelly/ghas-utils.git | ||
``` | ||
2. Navigate to the cloned repository: | ||
```bash | ||
cd ghas-utils | ||
``` | ||
3. Install the required Python libraries: | ||
```bash | ||
pip3 install requests | ||
``` | ||
or | ||
|
||
```bash | ||
pip3 install -r requests.txt | ||
``` | ||
# GitHub Personal Access Token | ||
|
||
## Usage | ||
All these example require the use of a personal access token. See [Setting a Personal Access Token for your Organization](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization). | ||
|
||
1. Create a [Github Personal Access Token](https://docs.github.com/en/enterprise-server@3.6/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) and set the value in a `GITHUB_ACCESS_TOKEN` environment variable. Your personal access token will start with `github_pat_` | ||
* This script is tested with these permissions: | ||
|
||
![Permissions](./doc/gh_pat_permissions.png) | ||
|
||
NOTE: For organizations which you are not an owner, please see [Setting a Personal Access Token for your Organization](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization). If you leverage a personal access token to read organization repositories, you will need to enable this policy, otherwise only public repositories will be readable. You will need one personal access token per organization. | ||
|
||
2. Open `ghas-scan.py` in your favorite text editor. | ||
3. Replace `owner_type` variabe value with `user` or `org`. | ||
4. Replace `owner_name` variable value with the corresponding user or org name. | ||
5. Set `skip_forks` to `True` if you want to omit forked repos from the results. | ||
6. Run the script: | ||
```bash | ||
python3 ghas-scan.py | ||
``` | ||
|
||
### Output and Example | ||
|
||
Output is written to `github_data.csv` at the repository root. It looks something like this: | ||
|
||
``` | ||
Getting list of repositories... | ||
Fetching repo security configs... | ||
CSV file 'github_data.csv' written successfully. | ||
Total repositories: 16 | ||
Total public repositories: 16 | ||
Percent of repositories that are forked: 0.0% | ||
Percent of repositories with Codeowners: 6.25% | ||
Percent of repositories with Secrets Scanning Enabled: 12.5% | ||
Percent of repositories with Secrets Push Protection Enabled: 12.5% | ||
Total number of open critical and high code scanning alerts: 0 | ||
Total number of open critical dependabot alerts: 0 | ||
Done. | ||
``` | ||
|
||
You can see an example in [./example/example_output.csv](./example/example_output.csv). This is just a basic example to give you an idea of the scehma. | ||
|
||
# References | ||
|
||
* [Github REST API Documentation](https://docs.github.com/en/rest) | ||
* [Secret Scanning API](https://docs.github.com/en/rest/secret-scanning/secret-scanning) | ||
* [Code Scanning API](https://docs.github.com/en/rest/code-scanning/code-scanning) | ||
* [Dependabot Alerts API](https://docs.github.com/en/rest/dependabot/alerts) | ||
* [Setting a Personal Access Token for your Organization](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization) | ||
* [Managing Security Managers in your Organization](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization) |
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,28 @@ | ||
import requests | ||
import argparse | ||
|
||
def fetch_custom_properties(repo, gh_pat): | ||
headers = { | ||
"Accept": "application/vnd.github+json", | ||
"Authorization": f"Bearer {gh_pat}", | ||
"X-GitHub-Api-Version": "2022-11-28", | ||
} | ||
url = f"https://api.github.com/repos/{repo}/properties/values" | ||
response = requests.get(url, headers=headers) | ||
response.raise_for_status() # Raise exception if the request failed | ||
properties = response.json() | ||
for prop in properties: | ||
print(f"Custom Property Key:Value Pairs for repo: {repo}") | ||
print("-------------------------------") | ||
if not properties: | ||
print("The repository has no custom properties.") | ||
else: | ||
for prop in properties: | ||
print(f"{prop['property_name']}: {prop['value']}") | ||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser(description='Fetch custom properties for a GitHub repository.') | ||
parser.add_argument('--repo', required=True, help='Repository in the format "owner/repo"') | ||
parser.add_argument('--gh_pat', required=True, help='GitHub Personal Access Token') | ||
args = parser.parse_args() | ||
fetch_custom_properties(args.repo, args.gh_pat) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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,74 @@ | ||
This is a Python script that interacts with the GitHub API to fetch repository details and code scanning analysis information. | ||
Make sure the repository exists and your GitHub token has the necessary permissions to access it. | ||
|
||
## Prerequisites | ||
|
||
- Python 3.6 or higher | ||
- `requests` library | ||
|
||
## Installation | ||
|
||
1. Clone this repository: | ||
```bash | ||
git clone git@github.com:austimkelly/ghas-utils.git | ||
``` | ||
2. Navigate to the cloned repository: | ||
```bash | ||
cd ghas-utils | ||
``` | ||
3. Install the required Python libraries: | ||
```bash | ||
pip3 install requests | ||
``` | ||
or | ||
|
||
```bash | ||
pip3 install -r requests.txt | ||
``` | ||
|
||
## Usage | ||
|
||
1. Create a [Github Personal Access Token](https://docs.github.com/en/enterprise-server@3.6/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) and set the value in a `GITHUB_ACCESS_TOKEN` environment variable. Your personal access token will start with `github_pat_` | ||
* This script is tested with these permissions: | ||
|
||
![Permissions](./doc/gh_pat_permissions.png) | ||
|
||
NOTE: For organizations which you are not an owner, please see [Setting a Personal Access Token for your Organization](https://docs.github.com/en/organizations/managing-programmatic-access-to-your-organization/setting-a-personal-access-token-policy-for-your-organization). If you leverage a personal access token to read organization repositories, you will need to enable this policy, otherwise only public repositories will be readable. You will need one personal access token per organization. | ||
|
||
2. Open `ghas-scan.py` in your favorite text editor. | ||
3. Replace `owner_type` variable value with `user` or `org`. | ||
4. Replace `owner_name` variable value with the corresponding user or org name. | ||
5. Set `skip_forks` to `True` if you want to omit forked repos from the results. | ||
6. Run the script: | ||
```bash | ||
python3 ghas-scan.py | ||
``` | ||
|
||
### Output and Example | ||
|
||
Output is written to `github_data.csv` at the repository root. The console output will look like this: | ||
|
||
``` | ||
Getting list of repositories... | ||
Fetching repo security configs... | ||
CSV file 'github_data.csv' written successfully. | ||
Total repositories: 16 | ||
Total public repositories: 16 | ||
Percent of repositories that are forked: 0.0% | ||
Percent of repositories with Codeowners: 6.25% | ||
Percent of repositories with Secrets Scanning Enabled: 12.5% | ||
Percent of repositories with Secrets Push Protection Enabled: 12.5% | ||
Total number of open critical and high code scanning alerts: 0 | ||
Total number of open critical dependabot alerts: 0 | ||
Done. | ||
``` | ||
|
||
You can see an example CSV in [./example/example_output.csv](./example/example_output.csv). This is just a simple example to give you an idea of the schema. | ||
|
||
# References | ||
|
||
* [Github REST API Documentation](https://docs.github.com/en/rest) | ||
* [Secret Scanning API](https://docs.github.com/en/rest/secret-scanning/secret-scanning) | ||
* [Code Scanning API](https://docs.github.com/en/rest/code-scanning/code-scanning) | ||
* [Dependabot Alerts API](https://docs.github.com/en/rest/dependabot/alerts) | ||
* [Managing Security Managers in your Organization](https://docs.github.com/en/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization) |
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 |
---|---|---|
@@ -1,6 +1,5 @@ | ||
import argparse | ||
import requests | ||
import pprint | ||
import sys | ||
import json | ||
|
||
|
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,43 @@ | ||
This demo shows how to pull all security alerts for an organization. Because security alerts for dependabot, secrets, and code scanning all have a different schema, we need to use different queries to pull them. | ||
|
||
## API References | ||
|
||
* [Dependabot Alerts REST API](https://docs.github.com/en/rest/dependabot/alerts?apiVersion=2022-11-28) | ||
* [Code Scanning Alerts for your Organization REST API](https://docs.github.com/en/rest/code-scanning/code-scanning?apiVersion=2022-11-28#list-code-scanning-alerts-for-an-organization) | ||
* [Secret Scanning Alerts for your Organization REST API](https://docs.github.com/en/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#list-secret-scanning-alerts-for-an-organization) | ||
|
||
## Running the demo | ||
|
||
> NOTE: Running on private/internal repos may need to change the code to filter on the repo visibility. This is currently tested on public repos. | ||
`python3 fetch-org-alerts.py <org name> <your github PAT>` | ||
|
||
If you have it all set up right, you will get this output: | ||
|
||
``` | ||
Dependabot alerts for swell-consulting: 15 | ||
Writing alert to _reports/swell-consulting_dependencies_20240516090913.csv | ||
Code scanning alerts for swell-consulting: 19 | ||
Writing alert to _reports/swell-consulting_code_scanning_20240516090913.csv | ||
Secret scanning alerts for swell-consulting: 1 | ||
Writing alert to _reports/swell-consulting_secrets_20240516090913.csv | ||
Number of active and open secrets for swell-consulting: 0 | ||
Number of open critical alerts for dependencies for swell-consulting: 2 | ||
Number of open critical alerts for code scanning for swell-consulting: 19 | ||
``` | ||
|
||
As you can see from the console output, each REST API call writes results to a CSV file in the `_reports` directory. | ||
|
||
### Example Output | ||
|
||
> NOTE: The full schema is available. There has been no filtering on columns for this output. | ||
See the [example_outputs directory](./example_outputs/) for an example of the output file. | ||
|
||
## Use cases | ||
|
||
While the Security Overview at the Enterprise and Organization level can give you some aggrated metrics on the volume of alerts and access to the raw alerts, there are some cases where you own policy may need to be applied to programmatic access on process of alert data. Some examples include: | ||
|
||
* SLA adherence. You may want to track which alert classifications are out of SLA and take some additional action. | ||
* Mass updates. You need to make some decision to change the status of masses of alerts. | ||
* Deferring alerts. You may want to close some alerts with comments to defer them. Currently, there is no way to set a status to "defer" or otherwise track alerts that you want to revisit at a later date. |
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 |
---|---|---|
@@ -1,9 +1,16 @@ | ||
You can update security alerts for a particular alert number in a specific repository. There are 3 different APIs that will you to modify existing alerts: | ||
|
||
> WARNING: This is a working progress. The script is not fully functional yet. | ||
> Security alerts do not have the ability to add custom tags or custom resolutions. Additionally, there is no mechanism to snooze, silence or otherwise defer alerts for a later time. If you need to track these types of actions, you may want to consider automating specific text in the resolution/dismissed comments. | ||
1. [Update a Dependabot alert](https://docs.github.com/en/rest/dependabot/alerts?apiVersion=2022-11-28#update-a-dependabot-alert) - When updating a Dependabot alert, you can update the `state`, `dismissed_reason`, and `dismissed_comment` fields. | ||
1. [Update a code scanning alert](https://docs.github.com/en/rest/code-scanning/code-scanning?apiVersion=2022-11-28#update-a-code-scanning-alert) - When updating a code scanning alert, you can update the `state`, `dismissed_reason`, and `dismissed_comment` fields. | ||
1. [Update a secret scanning alert](https://docs.github.com/en/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28#update-a-secret-scanning-alert - Here you can update the `state`, `resolution`, and `resolution_comment` fields. | ||
|
||
# TODO: Example python script . . . | ||
# Running the sample script | ||
|
||
``` bash | ||
python3 update-security-alerts.py --repo "OWNER/REPO" --gh_token "YOUR-TOKEN" --alert_type "dependabot" --state "dismissed" --dismissed_reason "tolerable_risk" --dismissed_comment "This alert is accurate but we use a sanitizer." --alert_number "ALERT_NUMBER" | ||
``` | ||
|
Oops, something went wrong.