Skip to content

Commit 3235602

Browse files
authored
Filtering type of alerts to export and Dependabot alerts support GHES (#44)
* select features; dependabot for GHES 3.8; * linter fixes * linter fixes
1 parent 54c9bd9 commit 3235602

File tree

5 files changed

+132
-45
lines changed

5 files changed

+132
-45
lines changed

.env-sample

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
## GHES
2+
#export GITHUB_API_URL="https://GHES-instance.net/api/v3"
3+
#export GITHUB_SERVER_URL="https://GHES-instance.net"
4+
5+
export GITHUB_PAT="ghp_TOKEN"
6+
export GITHUB_REPORT_SCOPE="repository"
7+
export SCOPE_NAME="org/repo-name"
8+
export FEATURES="secretscanning,dependabot"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,6 @@ swap.md
133133

134134
# CSV files
135135
*.csv
136+
137+
# Ignore macos files
138+
.DS_Store

CONTRIBUTING.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,31 @@ Here are a few things you can do that will increase the likelihood of your pull
2121
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
2222
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
2323

24+
## Local development
25+
26+
After cloning your forked repository, you can set up your development environment by running the following commands:
27+
28+
```bash
29+
# Create a virtual environment
30+
python3 -m venv venv
31+
source venv/bin/activate
32+
33+
# Install dependencies
34+
pip3 install -r requirements.txt
35+
```
36+
37+
To execute the python script `main.py` locally you will need to setup the required environment variables. You can do this by making a copy of `.env-sample` into `.env` file in the root of the project and edit the values to match your environment.
38+
39+
```bash
40+
source .env
41+
```
42+
43+
You can now run the script locally:
44+
45+
```bash
46+
python3 main.py
47+
```
48+
2449
## Resources
2550

2651
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)

README.md

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,36 @@ Or for an enterprise:
6969
SCOPE_NAME: "enterprise-slug-goes-here"
7070
```
7171
72+
The list of all available options that can be set as environmental variables is below:
73+
74+
- `GITHUB_API_URL`: The URL of the GitHub API. Default value: `https://api.github.com`.
75+
- `GITHUB_SERVER_URL`: The URL of the GitHub server. Default value: `https://github.com`.
76+
- `GITHUB_PAT` or `GITHUB_TOKEN`: The personal access token (PAT) or token for authenticating with the GitHub API. If `GITHUB_PAT` is not set, the value of `GITHUB_TOKEN` is used if it is set. If neither is set, an error occurs.
77+
- `GITHUB_REPORT_SCOPE`: The scope of the report to generate. Valid values are `repository` (default), `organization` or `enterprise`.
78+
- `SCOPE_NAME` or `GITHUB_REPOSITORY`: The name of the repository, organization or enterprise to generate the report for. If `SCOPE_NAME` is not set, the value of `GITHUB_REPOSITORY` is used if it is set. If neither is set, an error occurs.
79+
- `FEATURES`: A comma-separated list of features to include in the report. Valid values are `codescanning`, `secretscanning`, `dependabot` or simply `all`. Default value: `all`.
80+
81+
The first two are only needed if you're running this in a GitHub Enterprise Server or GitHub AE environment. The last one is useful if you only want to get data on a specific feature. For example, if you only want to get data on secret scanning, you can set `FEATURES` to `secretscanning`. Here's just another example how you would configure this on a GitHub Enterprise Server:
82+
83+
```yaml
84+
- name: CSV export
85+
uses: advanced-security/ghas-to-csv@v2
86+
env:
87+
GITHUB_PAT: ${{ secrets.PAT }}
88+
GITHUB_API_URL: "https://github.example.com/api/v3"
89+
GITHUB_SERVER_URL: "https://github.example.com"
90+
GITHUB_REPORT_SCOPE: "enterprise"
91+
SCOPE_NAME: "enterprise-slug-goes-here"
92+
FEATURES: "secretscanning,codescanning"
93+
```
94+
7295
## Reporting
7396

7497
| | GitHub Enterprise Cloud | GitHub Enterprise Server (3.5+) | GitHub AE (M2) | Notes |
7598
| --- | --- | --- | --- | --- |
7699
| Secret scanning | :white_check_mark: Repo<br>:white_check_mark: Org<br>:white_check_mark: Enterprise | :white_check_mark: Repo<br>:white_check_mark: Org<br>:white_check_mark: Enterprise | :white_check_mark: Repo<br>:x: Org<br>:x: Enterprise | [API docs](https://docs.github.com/en/enterprise-cloud@latest/rest/reference/secret-scanning) |
77-
| Code scanning | :white_check_mark: Repo<br>:white_check_mark: Org<br>:white_check_mark: Enterprise | :white_check_mark: Repo<br>:white_check_mark: Org<br>:curly_loop: Enterprise | :white_check_mark: Repo<br>:x: Org<br>:curly_loop: Enterprise | [API docs](https://docs.github.com/en/enterprise-cloud@latest/rest/reference/code-scanning) |
78-
| Dependabot | :white_check_mark: Repo<br>:white_check_mark: Org<br>:white_check_mark: Enterprise | :x: | :x: | [API docs](https://docs.github.com/en/enterprise-cloud@latest/rest/dependabot/alerts) |
100+
| Code scanning | :white_check_mark: Repo<br>:white_check_mark: Org<br>:white_check_mark: Enterprise | :white_check_mark: Repo<br>:white_check_mark: Org<br>:curly_loop: Enterprise (3.5, 3.6) <br>:white_check_mark: Enterprise (3.7+) | :white_check_mark: Repo<br>:x: Org<br>:curly_loop: Enterprise | [API docs](https://docs.github.com/en/enterprise-cloud@latest/rest/reference/code-scanning) |
101+
| Dependabot | :white_check_mark: Repo<br>:white_check_mark: Org<br>:white_check_mark: Enterprise | :white_check_mark: Repo (3.8+)<br>:white_check_mark: Org (3.8+)<br>:white_check_mark: Enterprise (3.8+) | :x: | [API docs](https://docs.github.com/en/enterprise-cloud@latest/rest/dependabot/alerts) |
79102

80103
:information_source: All of this reporting requires either public repositories or a GitHub Advanced Security license.
81104

@@ -143,7 +166,8 @@ nginx-pid/
143166

144167
## But it doesn't do THIS THING
145168

146-
The API docs are [here](https://docs.github.com/en/enterprise-cloud@latest) and pull requests are welcome! :heart:
169+
The API docs are [here](https://docs.github.com/en/enterprise-cloud@latest) and pull requests are welcome! :heart:.
170+
See [CONTRIBUTING](CONTRIBUTING.md) for more information.
147171

148172
## Other notes
149173

main.py

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,22 @@
88
- PAT of appropriate scope (assumes the workflow token if not specified)
99
- Report scope ("enterprise", "organization", "repository")
1010
- Enterprise slug OR organization name OR repository name
11+
- Features to run (comma separated list of "secretscanning", "codescanning", "dependabot")
1112
1213
Outputs:
1314
- CSV file of secret scanning alerts
1415
- CSV file of code scanning alerts
15-
16-
TODO: dependabot alerts
16+
- CSV file of Dependabot alerts
1717
"""
1818

1919
# Import modules
2020
from src import code_scanning, dependabot, enterprise, secret_scanning
2121
import os
2222

23+
24+
# Define the available features
25+
FEATURES = ["secretscanning", "codescanning", "dependabot"]
26+
2327
# Read in config values
2428
if os.environ.get("GITHUB_API_URL") is None:
2529
api_endpoint = "https://api.github.com"
@@ -46,72 +50,95 @@
4650
else:
4751
scope_name = os.environ.get("SCOPE_NAME")
4852

53+
if os.environ.get("FEATURES") is None:
54+
features = FEATURES
55+
else:
56+
if os.environ.get("FEATURES") == "all":
57+
features = FEATURES
58+
else:
59+
features = os.environ.get("FEATURES").split(",")
60+
for f in features:
61+
if f not in FEATURES:
62+
print(
63+
f"Invalid feature: {f}. Proceeding without. Valid features are: {FEATURES}"
64+
)
65+
features.remove(f)
66+
67+
4968
# Do the things!
5069
if __name__ == "__main__":
70+
print("Starting GitHub security report...")
71+
# enterprise scope
5172
if report_scope == "enterprise":
5273
# secret scanning
53-
secrets_list = secret_scanning.get_enterprise_secret_scanning_alerts(
54-
api_endpoint, github_pat, scope_name
55-
)
56-
secret_scanning.write_enterprise_secrets_list(secrets_list)
57-
# code scanning
58-
if enterprise.get_enterprise_version(api_endpoint) != "GHEC":
59-
repo_list = enterprise.get_repo_report(url, github_pat)
60-
cs_list = code_scanning.list_enterprise_server_code_scanning_alerts(
61-
api_endpoint, github_pat, repo_list
62-
)
63-
code_scanning.write_enterprise_server_cs_list(cs_list)
64-
else:
65-
cs_list = code_scanning.list_enterprise_cloud_code_scanning_alerts(
74+
if "secretscanning" in features:
75+
secrets_list = secret_scanning.get_enterprise_secret_scanning_alerts(
6676
api_endpoint, github_pat, scope_name
6777
)
68-
code_scanning.write_enterprise_cloud_cs_list(cs_list)
78+
secret_scanning.write_enterprise_secrets_list(secrets_list)
79+
# code scanning
80+
if "codescanning" in features:
81+
version = enterprise.get_enterprise_version(api_endpoint)
82+
# for GHES version 3.5 and 3.6 we need to loop through each repo and use the repo level api to get the code scanning alerts
83+
# for 3.7 and above we use the enterprise level api to get the code scanning alerts
84+
if version.startswith("3.5") or version.startswith("3.6"):
85+
repo_list = enterprise.get_repo_report(url, github_pat)
86+
cs_list = code_scanning.list_enterprise_server_code_scanning_alerts(
87+
api_endpoint, github_pat, repo_list
88+
)
89+
code_scanning.write_enterprise_server_cs_list(cs_list)
90+
else:
91+
cs_list = code_scanning.list_enterprise_cloud_code_scanning_alerts(
92+
api_endpoint, github_pat, scope_name
93+
)
94+
code_scanning.write_enterprise_cloud_cs_list(cs_list)
6995
# dependabot alerts
70-
if enterprise.get_enterprise_version(api_endpoint) == "GHEC":
96+
if "dependabot" in features:
7197
dependabot_list = dependabot.list_enterprise_dependabot_alerts(
7298
api_endpoint, github_pat, scope_name
7399
)
74100
dependabot.write_org_or_enterprise_dependabot_list(dependabot_list)
75-
else:
76-
pass
77-
101+
# organization scope
78102
elif report_scope == "organization":
79103
# code scanning
80-
cs_list = code_scanning.list_org_code_scanning_alerts(
81-
api_endpoint, github_pat, scope_name
82-
)
83-
code_scanning.write_org_cs_list(cs_list)
104+
if "codescanning" in features:
105+
cs_list = code_scanning.list_org_code_scanning_alerts(
106+
api_endpoint, github_pat, scope_name
107+
)
108+
code_scanning.write_org_cs_list(cs_list)
84109
# dependabot alerts
85-
if enterprise.get_enterprise_version(api_endpoint) == "GHEC":
110+
if "dependabot" in features:
86111
dependabot_list = dependabot.list_org_dependabot_alerts(
87112
api_endpoint, github_pat, scope_name
88113
)
89114
dependabot.write_org_or_enterprise_dependabot_list(dependabot_list)
90-
else:
91-
pass
115+
92116
# secret scanning
93-
secrets_list = secret_scanning.get_org_secret_scanning_alerts(
94-
api_endpoint, github_pat, scope_name
95-
)
96-
secret_scanning.write_org_secrets_list(secrets_list)
117+
if "secretscanning" in features:
118+
secrets_list = secret_scanning.get_org_secret_scanning_alerts(
119+
api_endpoint, github_pat, scope_name
120+
)
121+
secret_scanning.write_org_secrets_list(secrets_list)
122+
# repository scope
97123
elif report_scope == "repository":
98124
# code scanning
99-
cs_list = code_scanning.list_repo_code_scanning_alerts(
100-
api_endpoint, github_pat, scope_name
101-
)
102-
code_scanning.write_repo_cs_list(cs_list)
125+
if "codescanning" in features:
126+
cs_list = code_scanning.list_repo_code_scanning_alerts(
127+
api_endpoint, github_pat, scope_name
128+
)
129+
code_scanning.write_repo_cs_list(cs_list)
103130
# dependabot alerts
104-
if enterprise.get_enterprise_version(api_endpoint) == "GHEC":
131+
if "dependabot" in features:
105132
dependabot_list = dependabot.list_repo_dependabot_alerts(
106133
api_endpoint, github_pat, scope_name
107134
)
108135
dependabot.write_repo_dependabot_list(dependabot_list)
109-
else:
110-
pass
136+
111137
# secret scanning
112-
secrets_list = secret_scanning.get_repo_secret_scanning_alerts(
113-
api_endpoint, github_pat, scope_name
114-
)
115-
secret_scanning.write_repo_secrets_list(secrets_list)
138+
if "secretscanning" in features:
139+
secrets_list = secret_scanning.get_repo_secret_scanning_alerts(
140+
api_endpoint, github_pat, scope_name
141+
)
142+
secret_scanning.write_repo_secrets_list(secrets_list)
116143
else:
117144
exit("invalid report scope")

0 commit comments

Comments
 (0)