Skip to content

Commit 9ee94cb

Browse files
Merge branch 'cfn-guard-action'
2 parents 753ed62 + 23e10cf commit 9ee94cb

12 files changed

+2310
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
name: Security Guardian
2+
on:
3+
pull_request: {}
4+
5+
# Triggered from a separate job when a review is added
6+
workflow_run:
7+
workflows: [PR Linter Trigger]
8+
types:
9+
- completed
10+
11+
# Trigger when a status is updated (CodeBuild leads to statuses)
12+
status: {}
13+
14+
# Trigger when a check suite is completed (GitHub actions and CodeCov create checks)
15+
check_suite:
16+
types: [completed]
17+
18+
jobs:
19+
download-if-workflow-run:
20+
runs-on: ubuntu-latest
21+
outputs:
22+
pr_number: ${{ steps.pr_output.outputs.pr_number }}
23+
pr_sha: ${{ steps.pr_output.outputs.pr_sha }}
24+
# if conditions on all individual steps because subsequent jobs depend on this job
25+
# and we cannot skip it entirely
26+
steps:
27+
- name: 'Download workflow_run artifact'
28+
if: github.event_name == 'workflow_run'
29+
uses: dawidd6/action-download-artifact@v9
30+
with:
31+
run_id: ${{ github.event.workflow_run.id }}
32+
name: pr_info
33+
path: pr/
34+
search_artifacts: true
35+
36+
- name: 'Determine PR info'
37+
# PR info comes from the artifact if downloaded, or GitHub context if not.
38+
if: github.event_name == 'workflow_run'
39+
id: 'pr_output'
40+
run: |
41+
if [[ ! -f pr/pr_number ]]; then
42+
echo "${{ github.event.pull_request.number }}" > pr/pr_number
43+
fi
44+
if [[ ! -f pr/pr_sha ]]; then
45+
echo "${{ github.event.pull_request.head.sha }}" > pr/pr_sha
46+
fi
47+
cat pr/*
48+
echo "pr_number=$(cat pr/pr_number)" >> "$GITHUB_OUTPUT"
49+
echo "pr_sha=$(cat pr/pr_sha)" >> "$GITHUB_OUTPUT"
50+
51+
run-security-guardian:
52+
# Necessary to have sufficient permissions to write to the PR
53+
permissions:
54+
contents: read
55+
pull-requests: write
56+
statuses: read
57+
issues: read
58+
checks: read
59+
runs-on: ubuntu-latest
60+
needs: download-if-workflow-run
61+
steps:
62+
- name: Checkout
63+
uses: actions/checkout@v4
64+
65+
- name: Get list of changed .template.json files
66+
id: filter_files
67+
run: |
68+
echo "Getting changed CloudFormation templates..."
69+
mkdir -p changed_templates
70+
71+
git fetch origin main --depth=1
72+
73+
base_sha="${{ github.event.pull_request.base.sha }}"
74+
head_sha="${{ github.event.pull_request.head.sha }}"
75+
if [[ -z "$base_sha" ]]; then base_sha=$(git merge-base origin/main HEAD); fi
76+
if [[ -z "$head_sha" ]]; then head_sha=HEAD; fi
77+
78+
git diff --name-status "$base_sha" "$head_sha" \
79+
| grep -E '^(A|M)\s+.*\.template\.json$' \
80+
| awk '{print $2}' > changed_files.txt || true
81+
82+
while IFS= read -r file; do
83+
if [ -f "$file" ]; then
84+
safe_name=$(echo "$file" | sed 's|/|_|g')
85+
cp "$file" "changed_templates/$safe_name"
86+
else
87+
echo "::warning::Changed file not found in workspace: $file"
88+
fi
89+
done < changed_files.txt
90+
91+
if [ -s changed_files.txt ]; then
92+
echo "files_changed=true" >> $GITHUB_OUTPUT
93+
else
94+
echo "files_changed=false" >> $GITHUB_OUTPUT
95+
fi
96+
97+
- name: Install cfn-guard
98+
if: steps.filter_files.outputs.files_changed == 'true'
99+
run: |
100+
mkdir -p $HOME/.local/bin
101+
curl -L -o cfn-guard.tar.gz https://github.com/aws-cloudformation/cloudformation-guard/releases/latest/download/cfn-guard-v3-x86_64-ubuntu-latest.tar.gz
102+
tar -xzf cfn-guard.tar.gz
103+
mv cfn-guard-v3-*/cfn-guard $HOME/.local/bin/cfn-guard
104+
chmod +x $HOME/.local/bin/cfn-guard
105+
echo "$HOME/.local/bin" >> $GITHUB_PATH
106+
107+
- name: Install & Build security-guardian
108+
if: steps.filter_files.outputs.files_changed == 'true'
109+
run: yarn install --frozen-lockfile && cd tools/@aws-cdk/security-guardian && yarn build
110+
111+
- name: Run cfn-guard if templates changed
112+
if: steps.filter_files.outputs.files_changed == 'true'
113+
uses: ./tools/@aws-cdk/security-guardian
114+
with:
115+
data_directory: './changed_templates'
116+
rule_set_path: './tools/@aws-cdk/security-guardian/rules/trust_scope_rules.guard'
117+
show_summary: 'fail'
118+
output_format: 'single-line-summary'
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
*.js
2+
*.js.map
3+
*.d.ts
4+
dist
5+
node_modules
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# Security Guardian
2+
3+
A GitHub Action tool designed to validate changed AWS CloudFormation templates against custom [cfn-guard](https://github.com/aws-cloudformation/cloudformation-guard) rules. Supports both local paths and remote URLs for rule sets.
4+
5+
---
6+
7+
## 🚀 Features
8+
9+
- Validates only changed `*.template.json` files in PRs
10+
- Supports `cfn-guard v3`
11+
- Accepts rules from a local file or remote URL
12+
- Outputs validation results in summary format
13+
14+
---
15+
16+
## 📦 Inputs
17+
18+
| Name | Description | Required | Default |
19+
|------------------|-------------------------------------------------------------------|----------|---------|
20+
| `data_directory` | Directory containing templates to validate | ✅ Yes | |
21+
| `rule_file_path` | Local path to the rules file | ✅ Yes | |
22+
| `show_summary` | Whether to show summary output (`fail`, `warn`, `none`) | ❌ No | `fail` |
23+
| `output_format` | Output format (`single-line-summary`, `json`, etc.) | ❌ No | `single-line-summary` |
24+
25+
> `data_directory` and `rule_file_path` must be set.
26+
27+
---
28+
29+
## 🛠️ Usage
30+
31+
```yaml
32+
- name: Run CFN Guard
33+
uses: ./tools/@aws-cdk/security-guardian
34+
with:
35+
data_directory: './changed_templates'
36+
rule_set_path: './tools/@aws-cdk/security-guardian/rules/trust_scope_rules.guard'
37+
show_summary: 'fail'
38+
output_format: 'single-line-summary'
39+
```
40+
41+
---
42+
43+
## 🧪 Local Development
44+
45+
### 1. Build
46+
```bash
47+
npm install
48+
npm run build
49+
```
50+
51+
### 2. Run Locally
52+
```bash
53+
node dist/index.js \
54+
--data_directory=./changed_templates \
55+
--rule_file_path=./rules.guard \
56+
--output_format=single-line-summary \
57+
--show_summary=fail
58+
```
59+
60+
---
61+
62+
## 📝 License
63+
64+
```text
65+
Licensed under the Apache License, Version 2.0 (the "License");
66+
you may not use this file except in compliance with the License.
67+
You may obtain a copy of the License at
68+
69+
http://www.apache.org/licenses/LICENSE-2.0
70+
71+
Unless required by applicable law or agreed to in writing, software
72+
distributed under the License is distributed on an "AS IS" BASIS,
73+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74+
See the License for the specific language governing permissions and
75+
limitations under the License.
76+
```
77+
78+
---
79+
80+
## 👏 Contributing
81+
82+
PRs are welcome! Please follow conventional commit messages and test your changes before opening a pull request.
83+
84+
---
85+
86+
## 📣 Acknowledgments
87+
88+
Built on top of [cfn-guard](https://github.com/aws-cloudformation/cloudformation-guard) and [GitHub Actions Toolkit](https://github.com/actions/toolkit).
89+
90+
---
91+
92+
Happy Guarding! 🛡️
93+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: 'Security Guardian'
2+
description: 'Security Guardian for custom or granular guard rules'
3+
4+
inputs:
5+
data_directory:
6+
description: "Path to CloudFormation templates"
7+
required: true
8+
rule_set_path:
9+
description: "Path to a single .guard file locally"
10+
required: true
11+
show_summary:
12+
description: "cfn-guard summary output. Options are all, pass, fail, skip or none"
13+
required: false
14+
default: "fail"
15+
output_format:
16+
description: "cfn-guard output format. Options: json, yaml, single-line-summary"
17+
required: false
18+
default: "single-line-summary"
19+
20+
runs:
21+
using: node20
22+
main: dist/index.js
23+
24+
branding:
25+
icon: shield
26+
color: red

tools/@aws-cdk/security-guardian/package-lock.json

Lines changed: 116 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "security-guardian",
3+
"version": "1.0.0",
4+
"main": "dist/index.js",
5+
"scripts": {
6+
"build": "tsc",
7+
"prepare": "npm run build"
8+
},
9+
"dependencies": {
10+
"@actions/core": "^1.10.0",
11+
"@actions/exec": "^1.1.1"
12+
},
13+
"devDependencies": {
14+
"@types/node": "^22.14.0",
15+
"typescript": "^5.2.2"
16+
}
17+
}

0 commit comments

Comments
 (0)