Skip to content

Commit 2562ceb

Browse files
committed
feat: initial commit
0 parents  commit 2562ceb

21 files changed

Lines changed: 1442 additions & 0 deletions

File tree

.editorconfig

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[*]
2+
indent_style = space
3+
indent_size = 2
4+
end_of_line = lf
5+
insert_final_newline = true
6+
trim_trailing_whitespace = true
7+
charset = utf-8
8+
9+
[{Dockerfile,Dockerfile.*}]
10+
indent_size = 4
11+
tab_width = 4
12+
13+
[{Makefile,makefile,GNUmakefile}]
14+
indent_style = tab
15+
indent_size = 4
16+
17+
[Makefile.*]
18+
indent_style = tab
19+
indent_size = 4
20+
21+
[**/*.{go,mod,sum}]
22+
indent_style = tab
23+
indent_size = unset
24+
25+
[**/*.py]
26+
indent_size = 4

.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
APP_DEBUG_ENABLED=true
2+
APP_SLACK_CHANNEL=
3+
APP_SLACK_TOKEN=
4+
APP_AWS_CONSOLE_URL=https://console.aws.amazon.com
5+
APP_AWS_ACCESS_PORTAL_URL=
6+
APP_AWS_ACCESS_ROLE_NAME=

.github/.dependabot.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "github-actions"
4+
directory: "/"
5+
schedule:
6+
interval: "daily"

.github/workflows/release.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: release
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout Code
16+
uses: actions/checkout@v3
17+
- name: Bump Version
18+
id: tag_version
19+
uses: mathieudutour/github-tag-action@v6.1
20+
with:
21+
github_token: ${{ secrets.GITHUB_TOKEN }}
22+
default_bump: minor
23+
custom_release_rules: bug:patch:Fixes,chore:patch:Chores,docs:patch:Documentation,feat:minor:Features,refactor:minor:Refactors,test:patch:Tests,ci:patch:Development,dev:patch:Development
24+
- name: Create Release
25+
uses: ncipollo/release-action@v1.12.0
26+
with:
27+
tag: ${{ steps.tag_version.outputs.new_tag }}
28+
name: ${{ steps.tag_version.outputs.new_tag }}
29+
body: ${{ steps.tag_version.outputs.changelog }}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: semantic-check
2+
on:
3+
pull_request_target:
4+
types:
5+
- opened
6+
- edited
7+
- synchronize
8+
9+
permissions:
10+
contents: read
11+
pull-requests: read
12+
13+
jobs:
14+
main:
15+
name: Semantic Commit Message Check
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout Code
19+
uses: actions/checkout@v3
20+
- uses: amannn/action-semantic-pull-request@v5.2.0
21+
name: Check PR for Semantic Commit Message
22+
env:
23+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24+
with:
25+
requireScope: false
26+
validateSingleCommit: true

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
!**/.gitkeep
2+
3+
tmp/
4+
dist/
5+
.DS_Store
6+
7+
.local/
8+
.env
9+
10+
cognito-hooks-go
11+
main
12+

AGENTS.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Agent Guidelines
2+
3+
## Build & Test
4+
- **Build Lambda**: `GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -C cmd/lambda -o ../../dist/bootstrap`
5+
- **Test all**: `make test` (runs with `-race -count=1`)
6+
- **Test single package**: `go test -race -count=1 ./internal/app`
7+
- **Test single function**: `go test -race -count=1 ./internal/app -run TestFunctionName`
8+
- **Run sample locally**: `go run -C cmd/sample .` (requires `.env` file)
9+
- **Lint**: `go vet ./...` and `gofmt -l .`
10+
11+
## Code Style
12+
- **Imports**: stdlib, then blank line, then third-party, then local (e.g., `internal/`)
13+
- **Naming**: Go standard - `PascalCase` exports, `camelCase` private, `ALL_CAPS` for env vars prefixed with `APP_`
14+
- **Error handling**: return errors up the stack; use `fmt.Errorf` for wrapping
15+
- **Structs**: define types in package, constructors as `New()` or `NewTypeName()`; all methods must be public (PascalCase)
16+
- **Interfaces**: keep minimal (e.g., `SecurityHubEvent` has 2 methods)
17+
- **Formatting**: use `gofmt` (tabs for indentation)
18+
- **Comments**: rare, lowercase, short, concise; code should be self-documenting
19+
- **Code smells**: keep to minimum; prefer clear naming over comments
20+
21+
## Architecture
22+
- `cmd/lambda/main.go` - Lambda handler entry point
23+
- `cmd/sample/main.go` - Local development runner using fixtures
24+
- `internal/app/` - Core application logic and configuration
25+
- `internal/events/` - OCSF event parsing and Slack message formatting
26+
- `fixtures/samples.json` - Sample Security Hub v2 OCSF findings for testing
27+
28+
## Important Notes
29+
- This project is specifically for **AWS Security Hub v2** which uses OCSF (Open Cybersecurity Schema Framework) format
30+
- It is NOT compatible with the original AWS Security Hub (now called Security Hub CSPM) ASFF format
31+
- Security Hub v2 centralizes findings from GuardDuty, Inspector, Macie, IAM Access Analyzer, and Security Hub CSPM
32+
- Events use OCSF fields like `finding_info`, `metadata`, `severity`, `class_name`, etc.

Makefile

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# set mac-only linker flags only for go test (not global)
2+
UNAME_S := $(shell uname -s)
3+
TEST_ENV :=
4+
ifeq ($(UNAME_S),Darwin)
5+
TEST_ENV = CGO_LDFLAGS=-w
6+
endif
7+
8+
TEST_FLAGS := -race -count=1
9+
.PHONY: build-debug
10+
build-debug:
11+
GOOS=$(GOOS) GOARCH=$(GOARCH) go build -trimpath -ldflags "-s -w" -o dist/sample ./cmd/sample
12+
13+
.PHONY: debug
14+
debug:
15+
go run ./cmd/sample
16+
17+
.PHONY: test
18+
test:
19+
$(TEST_ENV) go test $(TEST_FLAGS) ./...
20+
21+
.PHONY: test-unit
22+
test-unit:
23+
$(TEST_ENV) go test $(TEST_FLAGS) ./internal/...
24+

README.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# aws-securityhub-integration-slack-go
2+
3+
AWS Lambda function that sends **AWS Security Hub v2** findings to Slack via EventBridge. **Security Hub v2** uses OCSF (Open Cybersecurity Schema Framework) format and centralizes findings from GuardDuty, Inspector, Macie, IAM Access Analyzer, and Security Hub CSPM.
4+
5+
> **Note:** This is for Security Hub v2 only. Not compatible with the original AWS Security Hub (now called Security Hub CSPM).
6+
7+
## Features
8+
9+
* **multi-service support** – handles findings from GuardDuty, Inspector, Macie, IAM Access Analyzer, and Security Hub CSPM
10+
* **ocsf format** – native support for Security Hub v2 OCSF schema
11+
* **eventbridge trigger** – findings invoke the Lambda function directly
12+
* **rich messages** – displays source service, severity, category, region, account, resource details, and remediation links
13+
* **config-driven** – all behavior controlled by environment variables
14+
* **severity filtering** – EventBridge rules can filter by severity (Critical/High only)
15+
16+
---
17+
18+
## Deployment
19+
20+
### Prerequisites
21+
22+
* AWS account with **AWS Security Hub v2** enabled in at least one region
23+
* **Important:** This must be Security Hub v2, not the original Security Hub (now Security Hub CSPM)
24+
* Security Hub v2 uses OCSF format and has product ARNs like `arn:aws:securityhub:region::productv2/aws/guardduty`
25+
* At least one integrated security service enabled (GuardDuty, Inspector, Macie, IAM Access Analyzer, or Security Hub CSPM)
26+
* Slack App with a Bot Token (`chat:write` scope) installed in your workspace
27+
* Go ≥ 1.24
28+
* AWS CLI configured for the deployment account
29+
30+
### Steps
31+
32+
```bash
33+
git clone https://github.com/cruxstack/aws-securityhub-integration-slack-go.git
34+
cd aws-securityhub-integration-slack-go
35+
36+
# build static Linux binary for lambda
37+
mkdir -p dist
38+
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -C cmd/lambda -o ../../dist/bootstrap
39+
40+
# package
41+
cd dist && zip deployment.zip bootstrap && cd ..
42+
```
43+
44+
## Required Environment Variables
45+
46+
| name | example | purpose |
47+
| --------------------------- | ------------------------------------------ | ------------------------------------------------------------ |
48+
| `APP_SLACK_TOKEN` | `xoxb-…` | slack bot token (store in secrets manager) |
49+
| `APP_SLACK_CHANNEL` | `C000XXXXXXX` | channel id to post findings |
50+
51+
## Optional Environment Variables
52+
53+
| name | example | purpose | default |
54+
| --------------------------- | ------------------------------------------ | ------------------------------------------------------------ | --------------------------------- |
55+
| `APP_DEBUG_ENABLED` | `true` | verbose logging & event dump | `false` |
56+
| `APP_AWS_CONSOLE_URL` | `https://console.aws.amazon.com` | base AWS console URL | `https://console.aws.amazon.com` |
57+
| `APP_AWS_ACCESS_PORTAL_URL` | `https://myorg.awsapps.com/start` | AWS access portal URL (for federated access) | _(none - direct console links)_ |
58+
| `APP_AWS_ACCESS_ROLE_NAME` | `SecurityAuditor` | IAM role name for access portal | _(none - direct console links)_ |
59+
60+
## Create Lambda Function
61+
62+
1. **IAM role**
63+
* `AWSLambdaBasicExecutionRole` managed policy
64+
* no additional AWS API permissions are required
65+
2. **Lambda config**
66+
* Runtime: `al2023provided.al2023` (provided.al2 also works)
67+
* Handler: `bootstrap`
68+
* Architecture: `x86_64` or `arm64`
69+
* Upload `deployment.zip`
70+
* Set environment variables above
71+
3. **EventBridge rule**
72+
```json
73+
{
74+
"source": ["aws.securityhub"],
75+
"detail-type": ["Security Hub Findings - Imported"]
76+
}
77+
```
78+
Optional: Filter by severity (recommended for high-volume environments):
79+
```json
80+
{
81+
"source": ["aws.securityhub"],
82+
"detail-type": ["Security Hub Findings - Imported"],
83+
"detail": {
84+
"severity": ["Critical", "High"]
85+
}
86+
}
87+
```
88+
Or filter by specific source services:
89+
```json
90+
{
91+
"source": ["aws.securityhub"],
92+
"detail-type": ["Security Hub Findings - Imported"],
93+
"detail": {
94+
"metadata": {
95+
"product": {
96+
"name": ["GuardDuty", "Inspector"]
97+
}
98+
}
99+
}
100+
}
101+
```
102+
Target: the Lambda function.
103+
4. **Slack App**
104+
* Add `chat:write` and `chat:write.public`
105+
* Custom bot avatar: upload AWS Security Hub logo in the Slack App *App Icon*
106+
section.
107+
108+
109+
## Local Development
110+
111+
### Test with Samples
112+
113+
```bash
114+
cp .env.example .env # edit the values
115+
go run -C cmd/sample .
116+
```
117+
118+
The sample runner reads OCSF-formatted Security Hub v2 findings from `fixtures/samples.json`, wraps them in EventBridge events, and posts to Slack exactly as the live Lambda would.
119+

assets/slack/avatar.png

15.4 KB
Loading

0 commit comments

Comments
 (0)