Skip to content

Commit bf9a779

Browse files
committed
feat: total refactoring done on code
1 parent c1da321 commit bf9a779

29 files changed

+1307
-565
lines changed

.github/workflows/build.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
name: build
2+
3+
on:
4+
pull_request:
5+
push:
6+
7+
permissions:
8+
contents: read
9+
10+
jobs:
11+
build:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v3
15+
- uses: actions/setup-go@v3
16+
with:
17+
go-version: 1.18
18+
- uses: actions/cache@v3
19+
with:
20+
path: ~/go/pkg/mod
21+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
22+
restore-keys: |
23+
${{ runner.os }}-go-
24+
- run: go test -v ./...

.github/workflows/release.yml

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#
2+
# Releaser workflow setup
3+
# https://goreleaser.com/ci/actions/
4+
#
5+
name: release
6+
7+
# run only on tags
8+
on:
9+
push:
10+
tags:
11+
- 'v*'
12+
13+
permissions:
14+
contents: write # needed to write releases
15+
id-token: write # needed for keyless signing
16+
packages: write # needed for ghcr access
17+
18+
jobs:
19+
release:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v3
23+
with:
24+
fetch-depth: 0 # this is important, otherwise it won't checkout the full tree (i.e. no previous tags)
25+
- uses: actions/setup-go@v3
26+
with:
27+
go-version: 1.18
28+
- uses: actions/cache@v3
29+
with:
30+
path: ~/go/pkg/mod
31+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
32+
restore-keys: |
33+
${{ runner.os }}-go-
34+
- uses: sigstore/cosign-installer@v2.4.0 # installs cosign
35+
- uses: anchore/sbom-action/download-syft@v0.11.0 # installs syft
36+
37+
- name: dockerhub login
38+
uses: docker/login-action@v2
39+
with:
40+
username: ${{ secrets.DOCKER_USERNAME }}
41+
password: ${{ secrets.DOCKER_PASSWORD }}
42+
43+
- name: ghcr login
44+
uses: docker/login-action@v2 # login to ghcr
45+
with:
46+
registry: ghcr.io
47+
username: ${{ github.repository_owner }}
48+
password: ${{ secrets.GITHUB_TOKEN }}
49+
- uses: goreleaser/goreleaser-action@v3 # run goreleaser
50+
with:
51+
version: latest
52+
args: release --rm-dist
53+
env:
54+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.goreleaser.Dockerfile

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
FROM scratch
2+
COPY shomon /usr/local/bin/shomon
3+
ENTRYPOINT [ "/usr/local/bin/shomon" ]

.goreleaser.yaml

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
builds:
2+
- env:
3+
- CGO_ENABLED=0
4+
goos:
5+
- linux
6+
- darwin
7+
goarch:
8+
- amd64
9+
- arm64
10+
# ensures mod timestamp to be the commit timestamp
11+
mod_timestamp: '{{ .CommitTimestamp }}'
12+
binary: shomon
13+
flags:
14+
# trims path
15+
- -trimpath
16+
ldflags:
17+
# use commit date instead of current date as main.date
18+
# only needed if you actually use those things in your main package, otherwise can be ignored.
19+
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{ .CommitDate }}
20+
21+
# proxies from the go mod proxy before building
22+
# https://goreleaser.com/customization/gomod
23+
#gomod:
24+
# proxy: true
25+
26+
# config the checksum filename
27+
# https://goreleaser.com/customization/checksum
28+
checksum:
29+
name_template: 'checksums.txt'
30+
31+
# create a source tarball
32+
# https://goreleaser.com/customization/source/
33+
source:
34+
enabled: true
35+
36+
# creates SBOMs of all archives and the source tarball using syft
37+
# https://goreleaser.com/customization/sbom
38+
sboms:
39+
- artifacts: archive
40+
- id: source # Two different sbom configurations need two different IDs
41+
artifacts: source
42+
43+
# signs the checksum file
44+
# all files (including the sboms) are included in the checksum, so we don't need to sign each one if we don't want to
45+
# https://goreleaser.com/customization/sign
46+
signs:
47+
- cmd: cosign
48+
env:
49+
- COSIGN_EXPERIMENTAL=1
50+
certificate: '${artifact}.pem'
51+
args:
52+
- sign-blob
53+
- '--output-certificate=${certificate}'
54+
- '--output-signature=${signature}'
55+
- '${artifact}'
56+
artifacts: checksum
57+
output: true
58+
59+
60+
dockers:
61+
- image_templates:
62+
- "docker.io/kaansk/shomon:{{ .Tag }}"
63+
- "docker.io/kaansk/shomon:latest"
64+
- "ghcr.io/kaansk/shomon:{{ .Tag }}"
65+
- "ghcr.io/kaansk/shomon:latest"
66+
dockerfile: .goreleaser.Dockerfile
67+
build_flag_templates:
68+
- "--pull"
69+
- "--label=org.opencontainers.image.created={{.Date}}"
70+
- "--label=org.opencontainers.image.name={{.ProjectName}}"
71+
- "--label=org.opencontainers.image.revision={{.FullCommit}}"
72+
- "--label=org.opencontainers.image.version={{.Version}}"
73+
- "--label=org.opencontainers.image.source={{.GitURL}}"
74+
75+
76+
docker_signs:
77+
- cmd: cosign
78+
env:
79+
- COSIGN_EXPERIMENTAL=1
80+
artifacts: images
81+
output: true
82+
args:
83+
- 'sign'
84+
- '${artifact}'

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Taken from https://github.com/chemidy/smallest-secured-golang-docker-image
22

3-
FROM golang@sha256:244a736db4a1d2611d257e7403c729663ce2eb08d4628868f9d9ef2735496659 as builder
3+
FROM golang:alpine as builder
44

55
# Install git + SSL ca certificates.
66
# Git is required for fetching the dependencies.

README.md

+37-16
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,53 @@
1-
# [![ShoMon](./images/logo.png)]()
2-
3-
ShoMon is a shodan alert feeder for theHive written in GoLang. Takes advantage of Golang's goroutines with deferred recover to continuously monitor alerts from shodan and feed them into theHive as alerts.
1+
<p align="center">
2+
<img src="images/logo.png" />
3+
</p>
4+
<p align="center">
5+
ShoMon is a Shodan alert feeder for TheHive written in GoLang. With version 2.0, it is more powerful than ever!
6+
</p>
7+
8+
9+
# Functionalities
10+
* Can be used as Webhook OR Stream listener
11+
* Webhook listener opens a restful API endpoint for Shodan to send alerts. This means you need to make this endpoint available to public net
12+
* Stream listener connects to Shodan and fetches/parses the alert stream
13+
* Utilizes [shadowscatcher/shodan](https://github.com/shadowscatcher/shodan) (fantastic work) for Shodan interaction.
14+
* Alert specifics can be adjusted via conf.yaml or environment variables
15+
* Console logs are in JSON format and can be ingested by any other further log management tools
16+
* CI/CD via Github Actions ensures that a proper Release with changelogs, artifacts, images on ghcr and dockerhub will be provided
17+
* Provides a working [docker-compose file](docker-compose.yml) file for TheHive, dependencies
18+
* Super fast and Super mini in size
19+
* Complete code refactoring in v2.0 resulted in more modular, maintainable code
420

521
# Usage
6-
[![Help](./images/help1.png)]()
22+
* Parameters should be provided via ```conf.yaml``` or environment variables. Please see [config file](conf.yaml) and [docker-compose file](docker-compose.yml)
23+
* After conf or environment variables are set simply issue command:
24+
25+
`./shomon`
726

827
## Notes
9-
* Logs can be found in shodanmonitor.log under the same folder
10-
* Alert reference is md5("ip:port")
11-
* Default logging level is DEBUG. Can be changed via editing logwrapper
28+
* Alert reference is first 6 chars of md5("ip:port")
29+
* Only 1 mod can be active at a time. Webhook and Stream listener can not be activated together.
1230

1331
# Setup & Compile Instructions
1432
## Get latest compiled binary from releases
15-
1. Check [Releases] section.
33+
1. Check [Releases](https://github.com/KaanSK/shomon/releases/latest) section.
1634

1735
## Compile from source code
1836
1. Make sure that you have a working Golang workspace.
1937
2. `go build .`
2038
* `go build -ldflags="-s -w" .` could be used to customize compilation and produce smaller binary.
2139

22-
## Using Dockerfile
23-
1. `docker build -t shomon .`
24-
2. `docker run -it shomon -s {SHODANKEY} -t {THEHIVEKEY}`
40+
## Using [Dockerfile](Dockerfile)
41+
1. Edit [config file](conf.yaml) or provide environment variables to commands bellow
42+
2. `docker build -t shomon .`
43+
3. `docker run -it shomon`
44+
45+
## Using [docker-compose file](docker-compose.yml)
46+
1. Edit environment variables and configurations in [docker-compose file](docker-compose.yml)
47+
2. `docker-compose run -d`
2548

2649
# Credits
2750
* Logo Made via LogoMakr.com
28-
* `go-shodan` : https://github.com/ns3777k/go-shodan
29-
* logwrapper package : https://www.datadoghq.com/blog/go-logging/
30-
* Dockerfile : https://www.cloudreach.com/en/resources/blog/cts-build-golang-dockerfiles/
31-
32-
[Releases]: https://github.com/KaanSK/shomon/releases/latest
51+
* [shadowscatcher/shodan](https://github.com/shadowscatcher/shodan)
52+
* [Dockerfile Reference](https://www.cloudreach.com/en/resources/blog/cts-build-golang-dockerfiles/)
53+
* Release management with [GoReleaser](https://goreleaser.com)

conf.yaml

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
HIVE_URL: "http://localhost:9000"
2+
HIVE_KEY:
3+
HIVE_CASE_TEMPLATE:
4+
HIVE_TYPE: "SHODAN"
5+
HIVE_TAGS:
6+
- 'test:test2="test3"'
7+
- 'test4:test5="test6"'
8+
SHODAN_KEY:
9+
INCLUDE_BANNER: true
10+
LOG_LEVEL: DEBUG
11+
WEBHOOK: true
12+
WEBHOOK_ENDPOINT: "/"
13+
WEBHOOK_PORT: 8080

conf/conf.go

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package conf
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"os"
7+
"strings"
8+
9+
"github.com/knadh/koanf"
10+
"github.com/knadh/koanf/parsers/yaml"
11+
"github.com/knadh/koanf/providers/confmap"
12+
"github.com/knadh/koanf/providers/env"
13+
"github.com/knadh/koanf/providers/file"
14+
)
15+
16+
type ShomonConfig struct {
17+
HiveUrl string `koanf:"HIVE_URL"`
18+
HiveCaseTemplate string `koanf:"HIVE_CASE_TEMPLATE" `
19+
HiveKey string `koanf:"HIVE_KEY"`
20+
HiveTags []string `koanf:"HIVE_TAGS"`
21+
HiveType string `koanf:"HIVE_TYPE"`
22+
ShodanKey string `koanf:"SHODAN_KEY"`
23+
LogLevel string `koanf:"LOG_LEVEL"`
24+
IncludeBanner bool `koanf:"INCLUDE_BANNER"`
25+
Webhook bool `koanf:"WEBHOOK"`
26+
WebhookEndpoint string `koanf:"WEBHOOK_ENDPOINT"`
27+
WebhookPort int `koanf:"WEBHOOK_PORT"`
28+
}
29+
30+
func New() (conf ShomonConfig, err error) {
31+
newConfig := &ShomonConfig{}
32+
if err := newConfig.Setup(); err != nil {
33+
return *newConfig, err
34+
}
35+
return *newConfig, nil
36+
}
37+
38+
func (d *ShomonConfig) Setup() error {
39+
k := koanf.New(".")
40+
41+
//Default Values
42+
k.Load(confmap.Provider(map[string]interface{}{
43+
"HIVE_URL": "http://localhost:9000",
44+
"HIVE_KEY": "NO_KEY",
45+
"LOG_LEVEL": "INFO",
46+
}, "."), nil)
47+
48+
if err := k.Load(file.Provider("conf.yaml"), yaml.Parser()); err != nil {
49+
if errors.Is(err, os.ErrNotExist) {
50+
k.Load(env.Provider("SHOMON_", ".", func(s string) string {
51+
return strings.TrimPrefix(s, "SHOMON_")
52+
}), nil)
53+
} else {
54+
return err
55+
}
56+
}
57+
58+
k.Unmarshal("", &d)
59+
return nil
60+
}
61+
62+
func (d *ShomonConfig) Print() string {
63+
if d != nil {
64+
return fmt.Sprintf("%+v", d)
65+
}
66+
return ""
67+
}

conf/conf_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package conf
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestGetConf(t *testing.T) {
8+
conf, err := New()
9+
if err != nil {
10+
t.Errorf(err.Error())
11+
}
12+
if conf.LogLevel == "" {
13+
t.Errorf("Config could not be populated")
14+
}
15+
}

0 commit comments

Comments
 (0)