Skip to content

Commit

Permalink
Alerts updates progress v2 (#18)
Browse files Browse the repository at this point in the history
* working open and dismiss on dependabot alerts
* updating code scanning alerts working
* get secrets scanning working
  • Loading branch information
austimkelly committed May 20, 2024
1 parent 9dc2271 commit 1147dcb
Show file tree
Hide file tree
Showing 5 changed files with 1,885 additions and 15 deletions.
1 change: 1 addition & 0 deletions custom-properties/custom-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ GitHub's Custom Properties allow you to add metadata to repositories in your org
* [REST API Endpoints for custom properties](https://docs.github.com/en/rest/repos/custom-properties?apiVersion=2022-11-28) - You can use the REST API to view the custom properties that were assigned to a repository by the organization that owns the repository.
* [Repository Custom Properties GA and Ruleset Improvements](https://github.blog/changelog/2024-02-14-repository-custom-properties-ga-and-ruleset-improvements/) - There's a [good video here](https://www.youtube.com/watch?v=z0CYdcqZxyQ) that explains how to use custom properties and rulesets to manage your repositories.
* [Creating rulesets for repositories in your organization](https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-organization-settings/creating-rulesets-for-repositories-in-your-organization) - By [combining rulesets with custom properties](https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-organization-settings/creating-rulesets-for-repositories-in-your-organization#choosing-which-repositories-to-target-in-your-organization), you can define which policies apply to which repositories in your organization. Be sure to check out some of the [ruleset-recipes](https://github.com/github/ruleset-recipes) on GitHub you can import too!
* [Custom Properties roadmap issue](https://github.com/github/roadmap/issues/799) - This is the original roadmap issue for custom properties. Released in Feb 2024.

# Example Script to pull custom properties from a repository

Expand Down
86 changes: 81 additions & 5 deletions update-security-alerts/update-security-alerts.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,92 @@
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:
# GitHub REST API to Update Security Alerts

> WARNING: This is a working progress. The script is not fully functional yet.
You can update security alerts for a particular alert number in a specific repository. Note that you can only update one alert type and one alert ID for each API request. This example uses a common set of command-line parameters, however, the input values will vary depending on the alert type you want to update. As such, make sure to pay attention to the nuances of the input parameters for each alert type.

> 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.
## API References

There are 3 different APIs that will you to modify existing alerts:

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.
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.

> 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.
## Fetching the alerts

In order to get the alert IDs you want, you will need to identify them in advance with some specific API calls. Checkout the demo in this repository on [Pull All Org Alerts](../pull_all_org_security_alerts/fetch-org-alerts.md) to see how you can fetch all the alerts for a specific organization.


# Running the sample script

The [update-security-alerts.py](./update-security-alerts.py) script is a command-line tool can open or dismiss any security alert type. See the usage and example below for the difference between the alert types.

## Usage

``` 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"
usage: update-security-alerts.py [-h] --repo REPO --gh_token GH_TOKEN --alert_type
{dependabot,code-scanning,secret-scanning} --state STATE
[--dismissed_reason DISMISSED_REASON] [--dismissed_comment DISMISSED_COMMENT]
--alert_number ALERT_NUMBER

Update a security alert in a GitHub repository.

options:
-h, --help show this help message and exit
--repo REPO The GitHub repository to update security alerts for, in the format 'owner/repo'.
--gh_token GH_TOKEN The GitHub token used for authentication. Should have write security_event permissions.
--alert_type {dependabot,code-scanning,secret-scanning}
The type of the security alert. Can be 'dependabot', 'code-scanning', or 'secret-scanning'.
--state STATE The state of the security alert. For 'dependabot' and 'code-scanning' alerts, can be 'open' or
'dismissed'. For 'secret-scanning' alerts, can be 'open' or 'resolved'.
--dismissed_reason DISMISSED_REASON
The reason for dismissing the security alert. Required when '--state' is 'dismissed' for
'dependabot' and 'code-scanning' alerts, and when '--state' is 'resolved' for 'secret-scanning'
alerts.
--dismissed_comment DISMISSED_COMMENT
An optional comment about the dismissal of the security alert.
--alert_number ALERT_NUMBER
The number of the security alert to update.
```

## Dependabot

### Dismissing a Dependabot alert:

```bash
python3 update-security-alerts.py --repo "swell-consulting/swiss-cheese" --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 1
```

### Reopening a Dependabot alert:

``` bash
python3 update-security-alerts.py --repo "swell-consulting/swiss-cheese" --gh_token "YOUR_TOKEN" --alert_type dependabot --state open --alert_number 1
```

### Dismissing a Code Scanning alert:

```bash
python3 update-security-alerts.py --repo "swell-consulting/swiss-cheese" --gh_token "YOUR_TOKEN" --alert_type code-scanning --state open --alert_number 1
```

## Code Scanning

## Reopening a Code Scanning alert:

```bash
python3 update-security-alerts.py --repo "swell-consulting/swiss-cheese" --gh_token ""YOUR_TOEKN" --alert_type code-scanning --state dismissed --alert_number 1 --dismissed_reason "won't fix" --dismissed_comment "API testing"
```
## Secret Scanning
### Dismissing a Secret Scanning alert:
```bash
python3 update-security-alerts.py --repo "swell-consulting/swiss-cheese" --gh_token "YOUR_TOKEN" --alert_type secret-scanning --state resolved --dismissed_reason used_in_tests --dismissed_comment "secret API testing" --alert_number 1
```
### Reopening a Secret Scanning alert:
```bash
python3 update-security-alerts.py --repo "swell-consulting/swiss-cheese" --gh_token "YOUR_TOKEN --alert_type secret-scanning --state open --dismissed_reason used_in_tests --dismissed_comment "secret API testing" --alert_number 1
```
56 changes: 46 additions & 10 deletions update-security-alerts/update-security-alerts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,44 @@
import argparse

# Parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument("--repo", required=True, help="GitHub repository")
parser.add_argument("--gh_token", required=True, help="GitHub token")
parser.add_argument("--alert_type", required=True, choices=["dependabot", "code", "secret"], help="Alert type")
parser.add_argument("--state", required=True, choices=["dismissed", "open"], help="State")
parser.add_argument("--dismissed_reason", required=True, choices=["fix_started", "inaccurate", "no_bandwidth", "not_used", "tolerable_risk"], help="Dismissed reason")
parser.add_argument("--dismissed_comment", required=True, help="Dismissed comment")
parser.add_argument("--alert_number", required=True, help="Alert number")
parser = argparse.ArgumentParser(description='Update a security alert in a GitHub repository.')
parser.add_argument("--repo", required=True, help="The GitHub repository to update security alerts for, in the format 'owner/repo'.")
parser.add_argument("--gh_token", required=True, help="The GitHub token used for authentication. Should have write security_event permissions.")
parser.add_argument("--alert_type", required=True, choices=["dependabot", "code-scanning", "secret-scanning"], help="The type of the security alert. Can be 'dependabot', 'code-scanning', or 'secret-scanning'.")
parser.add_argument("--state", required=True, help="The state of the security alert. For 'dependabot' and 'code-scanning' alerts, can be 'open' or 'dismissed'. For 'secret-scanning' alerts, can be 'open' or 'resolved'.")
parser.add_argument("--dismissed_reason", help="The reason for dismissing the security alert. Required when '--state' is 'dismissed' for 'dependabot' and 'code-scanning' alerts, and when '--state' is 'resolved' for 'secret-scanning' alerts.")
parser.add_argument("--dismissed_comment", help="An optional comment about the dismissal of the security alert.")
parser.add_argument("--alert_number", required=True, help="The number of the security alert to update.")
args = parser.parse_args()

dependabot_reasons = ["fix_started", "inaccurate", "no_bandwidth", "not_used", "tolerable_risk"]
code_reasons = ["null", "false positive", "won't fix", "used in tests"]
secret_reasons = ["false_positive", "won't fix", "revoked", "used_in_tests", "null"]

if args.state == "dismissed":
if args.dismissed_reason is None:
parser.error("--dismissed_reason is required when --state is 'dismissed'")
elif args.alert_type == "dependabot" and args.dismissed_reason not in dependabot_reasons:
parser.error("Invalid --dismissed_reason for dependabot. Choices are: " + ", ".join(dependabot_reasons))
elif args.alert_type == "code-scanning" and args.dismissed_reason not in code_reasons:
parser.error("Invalid --dismissed_reason for code. Choices are: " + ", ".join(code_reasons))

if args.alert_type == "secret-scanning":
if args.state not in ["open", "resolved"]:
parser.error("Invalid --state for secret-scanning. Choices are: open, resolved")
if args.state == "resolved":
if args.dismissed_reason is None:
parser.error("--dismissed_reason is required when --alert_type is 'secret-scanning' and --state is 'resolved'")
elif args.dismissed_reason not in secret_reasons:
parser.error("Invalid --dismissed_reason for secret-scanning. Choices are: " + ", ".join(secret_reasons))


# Update a secret scanning alert
# API Endpoint: https://docs.github.com/en/rest/secret-scanning/secret-scanning?apiVersion=2022-11-28
# Update a dependabot alert
# API Endpoint: https://docs.github.com/en/rest/dependabot/alerts?apiVersion=2022-11-28#update-a-dependabot-alert
# Update a code scanning alert
# API Endpoint: https://docs.github.com/en/rest/code-scanning/code-scanning?apiVersion=2022-11-28#update-a-code-scanning-alert
url = f"https://api.github.com/repos/{args.repo}/{args.alert_type}/alerts/{args.alert_number}"

# Define the headers
Expand All @@ -25,10 +52,19 @@
# Define the data
data = {
"state": args.state,
"dismissed_reason": args.dismissed_reason,
"dismissed_comment": args.dismissed_comment

}

if args.state == "dismissed":
data["dismissed_reason"] = args.dismissed_reason
if args.dismissed_comment is not None:
data["dismissed_comment"] = args.dismissed_comment

if args.alert_type == "secret-scanning" and args.state == "resolved":
data["resolution"] = args.dismissed_reason
if args.dismissed_comment is not None:
data["resolution_comment"] = args.dismissed_comment

# Make the API request
response = requests.patch(url, headers=headers, json=data)

Expand Down
Loading

0 comments on commit 1147dcb

Please sign in to comment.