Skip to content

Commit 2a5dc00

Browse files
authored
Merge pull request #13 from advanced-security-demo/theztefan/candidate
Theztefan/candidate
2 parents 1bedcb5 + fde5367 commit 2a5dc00

26 files changed

+1748
-1437
lines changed

.env.sample

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
FREQUENCY=24
22
SCOPE=repository
3-
GITHUB_TOKEN=xxxx
3+
GITHUB_TOKEN=ghp_xxx
44
GITHUB_API_URL=https://api.github.com
5-
REPO=xxxx
6-
ORG=xxxx
7-
LOCAL_DEV=true
5+
GITHUB_REPOSITORY=repo
6+
GITHUB_OWNER=org
7+
GITHUB_ENTERPRISE=enterprise
8+
LOCAL_DEV=true
9+
CREATED_ALERTS_FILEPATH=new-alerts.json
10+
CLOSED_ALERTS_FILEPATH=resolved-alerts.json
11+
GITHUB_ACTION=true

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ npm-debug.log*
99
yarn-debug.log*
1010
yarn-error.log*
1111
lerna-debug.log*
12+
new-alerts.json
13+
resolved-alerts.json
1214

1315
# Diagnostic reports (https://nodejs.org/api/report.html)
1416
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @actions/actions-runtime
1+
* @ps-advanced-security

README.md

Lines changed: 81 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,105 @@
1-
<p align="center">
2-
<a href="https://github.com/actions/typescript-action/actions"><img alt="typescript-action status" src="https://github.com/actions/typescript-action/workflows/build-test/badge.svg"></a>
3-
</p>
1+
# Secret Scanning Alerts GitHub Action
42

5-
# Create a JavaScript Action using TypeScript
3+
This GitHub Action retrieves secret scanning alerts from GitHub and filters them based on a specified date range. It then saves the filtered alerts to files and outputs a summary of the new and resolved alerts.
64

7-
Use this template to bootstrap the creation of a TypeScript action.:rocket:
5+
You can use the ouput to create a GitHub issue or send a notification to Email, Slack, Teams, etc.
86

9-
This template includes compilation support, tests, a validation workflow, publishing, and versioning guidance.
107

11-
If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action)
8+
## How does it work?
129

13-
## Create an action from this template
10+
The code is realitvely simple. The flow is defined in `src/main.ts` and is as follows:
1411

15-
Click the `Use this Template` and provide the new repo details for your action
12+
1. Parse inputs using the `getInput()` function.
13+
2. Calculate the minimum date for the alert scan using the `calculateDateRange()` function.
14+
3. Retrieve secret scanning alerts for the specified scope by calling the GitHub Secret Scanning REST API.
15+
4. Filter the alerts based on the minimum date using the `filterAlerts()` function.
16+
5. Write the new alerts and resolved alerts to json files.
17+
6. Print the results as GitHub Actions summary.
18+
7. Set the `summary-markdown` output to make it available to other steps in the workflow.
1619

17-
## Code in Main
20+
## Usage
1821

19-
> First, you'll need to have a reasonably modern version of `node` handy. This won't work with versions older than 9, for instance.
22+
To use this action, add the following step to your workflow:
2023

21-
Install the dependencies
22-
```bash
23-
$ npm install
24-
```
25-
26-
Build the typescript and package it for distribution
27-
```bash
28-
$ npm run build && npm run package
29-
```
30-
31-
Run the tests :heavy_check_mark:
32-
```bash
33-
$ npm test
34-
35-
PASS ./index.test.js
36-
✓ throws invalid number (3ms)
37-
wait 500 ms (504ms)
38-
test runs (95ms)
39-
40-
...
41-
```
42-
43-
## Change action.yml
44-
45-
The action.yml defines the inputs and output for your action.
46-
47-
Update the action.yml with your name, description, inputs and outputs for your action.
48-
49-
See the [documentation](https://help.github.com/en/articles/metadata-syntax-for-github-actions)
50-
51-
## Change the Code
52-
53-
Most toolkit and CI/CD operations involve async operations so the action is run in an async function.
54-
55-
```javascript
56-
import * as core from '@actions/core';
57-
...
58-
59-
async function run() {
60-
try {
61-
...
62-
}
63-
catch (error) {
64-
core.setFailed(error.message);
65-
}
66-
}
67-
68-
run()
24+
```yaml
25+
- name: Secret Scanning Alerts
26+
uses: advanced-security/secret-scanning-custom-notifications/@v1
27+
with:
28+
frequency: 24 # hours
29+
scope: 'repository'
30+
repository: 'repo-name'
31+
new_alerts_filepath: 'new_alerts.json'
32+
closed_alerts_filepath: 'closed_alerts.json'
6933
```
7034
71-
See the [toolkit documentation](https://github.com/actions/toolkit/blob/master/README.md#packages) for the various packages.
35+
## Inputs
36+
This action requires the following inputs:
7237
73-
## Publish to a distribution branch
38+
- `frequency`: The frequency of the action. Valid values are daily, weekly, and monthly. Required.
39+
- `scope`: The scope of the action. Valid values are repo, org, and enterprise. Required.
40+
- `token`: The GitHub API token to use for the action. Required.
41+
- `new_alerts_filepath`: The path to the file where the new alerts should be stored for email attachment. Required.
42+
- `closed_alerts_filepath`: The path to the file where the closed alerts should be stored for email attachment. Required.
43+
- `api_url`: The GitHub API URL to use for the action. Needed only if you are using GitHub Enterprise Server. Optional.
44+
- `repo`: The repo to run the action on. Needed only if scope is repo and you intend to fetch alerts from other repos than the one where the action is running. Optional.
45+
- `org`: The org to run the action on. Needed only if scope is org and you intend to fetch alerts from other repos than the one where the action is running. Optional.
46+
- `enterprise`: The enterprise to run the action on. Required if you run it on the enterprise level. Optional.
7447

75-
Actions are run from GitHub repos so we will checkin the packed dist folder.
76-
77-
Then run [ncc](https://github.com/zeit/ncc) and push the results:
78-
```bash
79-
$ npm run package
80-
$ git add dist
81-
$ git commit -a -m "prod dependencies"
82-
$ git push origin releases/v1
83-
```
8448

85-
Note: We recommend using the `--license` option for ncc, which will create a license file for all of the production node modules used in your project.
49+
## Outputs
50+
This action has the following outputs:
8651

87-
Your action is now published! :rocket:
52+
- `summary-markdown`: A markdown formatted summary of the new and resolved alerts.
8853

89-
See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md)
9054

91-
## Validate
55+
## Example Workflow
9256

93-
You can now validate the action by referencing `./` in a workflow in your repo (see [test.yml](.github/workflows/test.yml))
57+
Run the action every 4 hours and upload the new and resolved alerts to an artifact if there are any new or resolved alerts.
9458

9559
```yaml
96-
uses: ./
97-
with:
98-
milliseconds: 1000
60+
name: Secret Scanning Alerts
61+
62+
on:
63+
schedule:
64+
- cron: '0 */6 * * 0' # Run every 4 hours
65+
jobs:
66+
secret-scanning-alerts:
67+
runs-on: ubuntu-latest
68+
69+
steps:
70+
- name: Secret Scanning Alerts
71+
uses: advanced-security/secret-scanning-custom-notifications/@v1
72+
with:
73+
frequency: 3000
74+
scope: 'repository'
75+
new_alerts_filepath: 'created_alerts.json'
76+
closed_alerts_filepath: 'closed_alerts.json'
77+
token: ${{ secrets.TOKEN }}
78+
79+
- name: Count the number of entries in the alert files
80+
id: count_alerts
81+
run: |
82+
created_alerts_count=$(jq '. | length' created_alerts.json)
83+
closed_alerts_count=$(jq '. | length' closed_alerts.json)
84+
echo "created_alerts_count=$created_alerts_count" >> $GITHUB_OUTPUT
85+
echo "closed_alerts_count=$closed_alerts_count" >> $GITHUB_OUTPUT
86+
87+
- name: Upload artifact
88+
if: steps.count_alerts.outputs.created_alerts_count > 0 || steps.count_alerts.outputs.closed_alerts_count > 0
89+
uses: actions/upload-artifact@v3
90+
with:
91+
name: my-artifact
92+
path: |
93+
created_alerts.json
94+
closed_alerts.json
9995
```
10096

101-
See the [actions tab](https://github.com/actions/typescript-action/actions) for runs of this action! :rocket:
10297

103-
## Usage:
98+
99+
## License
100+
This project is distributed under the [MIT license](LICENSE.md).
104101

105-
After testing you can [create a v1 tag](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) to reference the stable and latest V1 action
102+
## Contributing
103+
- Fork this repo
104+
- Work on your new feature
105+
- Create new Pull Request

__tests__/inputs.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { inputs } from "../src/utils/inputs";
2+
3+
describe("inputs", () => {
4+
it("should return an object with inputs when all environment variables are set", async () => {
5+
process.env.LOCAL_DEV = "true";
6+
process.env.FREQUENCY = "30";
7+
process.env.SCOPE = "org";
8+
process.env.GITHUB_TOKEN = "test-token";
9+
process.env.GITHUB_API_URL = "https://test-api-url.com";
10+
process.env.GITHUB_REPOSITORY = "test-repo";
11+
process.env.GITHUB_OWNER = "test-owner";
12+
process.env.GITHUB_ENTERPRISE = "test-enterprise";
13+
process.env.CREATED_ALERTS_FILEPATH = "test-new-alerts-filepath";
14+
process.env.CLOSED_ALERTS_FILEPATH = "test-closed-alerts-filepath";
15+
16+
const result = await inputs();
17+
expect(result).toHaveProperty("scope", "org");
18+
expect(result).toHaveProperty("frequency", 30);
19+
expect(result).toHaveProperty("api_token", "test-token");
20+
expect(result).toHaveProperty("apiURL", "https://test-api-url.com");
21+
expect(result).toHaveProperty("repo", "test-repo");
22+
expect(result).toHaveProperty("owner", "test-owner");
23+
expect(result).toHaveProperty("enterprise", "test-enterprise");
24+
expect(result).toHaveProperty("new_alerts_filepath", "test-new-alerts-filepath");
25+
expect(result).toHaveProperty("closed_alerts_filepath", "test-closed-alerts-filepath");
26+
27+
delete process.env.LOCAL_DEV;
28+
delete process.env.FREQUENCY;
29+
delete process.env.SCOPE;
30+
delete process.env.GITHUB_TOKEN;
31+
delete process.env.GITHUB_API_URL;
32+
delete process.env.GITHUB_REPOSITORY;
33+
delete process.env.GITHUB_ACTOR;
34+
delete process.env.GITHUB_ENTERPRISE;
35+
delete process.env.CREATED_ALERTS_FILEPATH;
36+
delete process.env.CLOSED_ALERTS_FILEPATH;
37+
});
38+
39+
it("should throw an error if frequency is not a number", async () => {
40+
process.env.FREQUENCY = "invalid-frequency";
41+
42+
await expect(inputs()).rejects.toThrowError("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'");
43+
44+
delete process.env.FREQUENCY;
45+
});
46+
47+
it("should throw an error if scope is not 'repo' or 'org'", async () => {
48+
process.env.SCOPE = "invalid-scope";
49+
50+
await expect(inputs()).rejects.toThrowError("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'");
51+
52+
delete process.env.SCOPE;
53+
});
54+
55+
it("should throw an error if GITHUB_TOKEN is not set", async () => {
56+
delete process.env.GITHUB_TOKEN;
57+
58+
await expect(inputs()).rejects.toThrowError("context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'");
59+
});
60+
});

__tests__/main.test.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)