Skip to content

Commit 4c635f1

Browse files
committed
Add Docker support for FastFinder with multi-platform builds
1 parent 2b09798 commit 4c635f1

19 files changed

+1201
-17
lines changed

.github/workflows/docker_build.yml

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: Docker Build Test
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- 'docker/**'
8+
- '*.go'
9+
- 'go.mod'
10+
- 'go.sum'
11+
- '.github/workflows/docker_build.yml'
12+
pull_request:
13+
branches: [ main ]
14+
paths:
15+
- 'docker/**'
16+
- '*.go'
17+
workflow_dispatch:
18+
19+
jobs:
20+
# Test builder Dockerfile (cross-compilation)
21+
test-builder:
22+
name: Test Multi-Platform Builder
23+
runs-on: ubuntu-latest
24+
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
29+
- name: Set up Docker Buildx
30+
uses: docker/setup-buildx-action@v3
31+
32+
- name: Build Linux binary
33+
uses: docker/build-push-action@v5
34+
with:
35+
context: .
36+
file: docker/Dockerfile.builder
37+
target: linux-builder
38+
push: false
39+
tags: fastfinder-linux-builder:test
40+
cache-from: type=gha
41+
cache-to: type=gha,mode=max
42+
43+
- name: Build Windows binary
44+
uses: docker/build-push-action@v5
45+
with:
46+
context: .
47+
file: docker/Dockerfile.builder
48+
target: windows-builder
49+
push: false
50+
tags: fastfinder-windows-builder:test
51+
cache-from: type=gha
52+
cache-to: type=gha,mode=max
53+
54+
- name: Extract binaries
55+
run: |
56+
mkdir -p bin
57+
docker build --target binaries --output type=local,dest=./bin -f docker/Dockerfile.builder .
58+
ls -lh bin/
59+
60+
- name: Verify binaries exist
61+
run: |
62+
if [ ! -f "bin/fastfinder-linux-amd64" ]; then
63+
echo "Linux binary not found!"
64+
exit 1
65+
fi
66+
if [ ! -f "bin/fastfinder-windows-amd64.exe" ]; then
67+
echo "Windows binary not found!"
68+
exit 1
69+
fi
70+
echo "✓ Both binaries built successfully"
71+
72+
- name: Test Linux binary
73+
run: |
74+
chmod +x bin/fastfinder-linux-amd64
75+
bin/fastfinder-linux-amd64 --version || echo "Version check not available"
76+
77+
- name: Upload binaries as artifacts
78+
uses: actions/upload-artifact@v4
79+
with:
80+
name: fastfinder-binaries
81+
path: |
82+
bin/fastfinder-linux-amd64
83+
bin/fastfinder-windows-amd64.exe
84+
retention-days: 7
85+
86+
# Test runtime Dockerfile
87+
test-runtime:
88+
name: Test Runtime Container
89+
runs-on: ubuntu-latest
90+
91+
steps:
92+
- name: Checkout code
93+
uses: actions/checkout@v4
94+
95+
- name: Set up Docker Buildx
96+
uses: docker/setup-buildx-action@v3
97+
98+
- name: Build runtime image
99+
uses: docker/build-push-action@v5
100+
with:
101+
context: .
102+
file: docker/Dockerfile.runtime
103+
push: false
104+
tags: fastfinder:test
105+
cache-from: type=gha
106+
cache-to: type=gha,mode=max
107+
108+
- name: Test runtime container
109+
run: |
110+
# Create test directories
111+
mkdir -p test-scan test-output
112+
echo "test file" > test-scan/test.txt
113+
114+
# Run container
115+
docker run --rm \
116+
-v $(pwd)/test-scan:/scan:ro \
117+
-v $(pwd)/examples:/rules:ro \
118+
-v $(pwd)/test-output:/output \
119+
fastfinder:test \
120+
--help
121+
122+
echo "✓ Runtime container works"
123+
124+
# Test docker-compose
125+
test-compose:
126+
name: Test Docker Compose
127+
runs-on: ubuntu-latest
128+
129+
steps:
130+
- name: Checkout code
131+
uses: actions/checkout@v4
132+
133+
- name: Validate docker-compose.yml
134+
run: |
135+
cd docker
136+
docker-compose config
137+
echo "✓ docker-compose.yml is valid"
138+
139+
- name: Test builder profile
140+
run: |
141+
cd docker
142+
docker-compose --profile build config
143+
echo "✓ Builder profile is valid"
144+
145+
- name: Test runtime profile
146+
run: |
147+
cd docker
148+
docker-compose --profile runtime config
149+
echo "✓ Runtime profile is valid"

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
.idea/
33
*.iml
44
.vscode/
5-
.history/
5+
.history/
6+
bin/

Icon.ico

66.4 KB
Binary file not shown.

README.md

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,35 @@ FastFinder is a powerful, lightweight incident response tool designed for cybers
5454
- 🪟 **Windows**: [Compilation Guide](README.windows-compilation.md)
5555
- 🐧 **Linux**: [Compilation Guide](README.linux-compilation.md)
5656

57+
### Docker Installation (No Dependencies Required!)
58+
59+
The easiest way to build FastFinder without installing any dependencies:
60+
61+
```bash
62+
# Build binaries for Linux and Windows
63+
cd docker
64+
make build-binaries
65+
66+
# Binaries will be in ./bin/
67+
# - fastfinder-linux-amd64
68+
# - fastfinder-windows-amd64.exe
69+
```
70+
71+
#### Docker Runtime Container
72+
73+
Run FastFinder inside a privileged Docker container to scan volumes or mounted filesystems:
74+
75+
```powershell
76+
# Build the runtime image (includes FastFinder + YARA + editors)
77+
.\docker-helper.ps1 build-runtime
78+
79+
# Run scan with configuration directory
80+
.\docker-helper.ps1 run-runtime -ConfigPath "C:\path\to\config_folder" -ScanPath "C:\data\to\scan"
81+
82+
# Interactive shell mode (no scan, just shell access)
83+
.\docker-helper.ps1 run-runtime -Interactive
84+
```
85+
5786
### Requirements
5887

5988
- **Runtime**: No dependencies required for pre-compiled binaries
@@ -105,7 +134,7 @@ fastfinder [OPTIONS]
105134
./fastfinder -b standalone_scanner.exe
106135
```
107136

108-
> 💡 **Tip**: FastFinder can run with standard user privileges, but administrative rights provide access to all system files.
137+
> 💡 **Tip**: FastFinder can run with standard user privileges, but administrative rights provide access to all system files.
109138
110139
### Scan and export file match according to your needs
111140
configuration examples are available [there](./examples)
@@ -143,13 +172,13 @@ eventforwarding:
143172
retain_files: 5 # Keep 5 old files
144173
http: # forward app activity with HTTP POST json data
145174
enabled: false
146-
url: "https://your-forwarder-url.com/api/events"
147-
ssl_verify: false
148-
timeout_seconds: 10
149-
headers:
175+
url: "https://your-forwarder-url.com/api/events"
176+
ssl_verify: false
177+
timeout_seconds: 10
178+
headers:
150179
Authorization: "Bearer YOUR_API_KEY"
151180
MY-CUSTOM-HEADER: "My-Header-Value"
152-
retry_count: 3
181+
retry_count: 3
153182
filters:
154183
event_types:
155184
- "error"
@@ -164,10 +193,34 @@ eventforwarding:
164193
* regular expressions are also available , just enclose paths with slashes (eg. /[0-9]{8}\\.exe/)
165194
* environment variables can also be used (eg. %TEMP%\\myfile.exe)
166195
196+
### YARA Rules Path Resolution
197+
198+
**Relative paths in YAML configuration are resolved relative to the configuration file location:**
199+
200+
```yaml
201+
input:
202+
content:
203+
yara:
204+
- "./example_rule_linux.yar" # Looks in same folder as config.yaml
205+
- "./subfolder/custom_rules.yar" # Looks in subfolder relative to config
206+
- "/absolute/path/to/rule.yar" # Absolute paths work as-is
207+
- "https://example.com/rules.yar" # URLs are also supported
208+
```
209+
210+
Example directory structure:
211+
```
212+
project/
213+
├── config.yaml
214+
├── example_rule_linux.yar # ✅ Found by "./example_rule_linux.yar"
215+
└── rules/
216+
└── custom.yar # ✅ Found by "./rules/custom.yar"
217+
```
218+
167219
### Important notes
168220
* input path are always case INSENSITIVE
169221
* content search on string (grep) are always case SENSITIVE
170222
* backslashes SHOULD NOT be escaped (except with regular expressions)
223+
* **YARA rules must exist** - missing rules will cause FastFinder to exit with an error
171224
For more informations, take a look at the [examples](./examples)
172225

173226
## 🤝 Contributing

configuration.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"io/ioutil"
77
"net/http"
8+
"path/filepath"
89
"regexp"
910
"strings"
1011

@@ -71,6 +72,14 @@ func (c *Configuration) getConfiguration(configFile string) *Configuration {
7172
var yamlContent []byte
7273
var err error
7374
configFile = strings.TrimSpace(configFile)
75+
configBaseDir := ""
76+
77+
if !IsValidUrl(configFile) {
78+
if absPath, err := filepath.Abs(configFile); err == nil {
79+
configFile = absPath
80+
configBaseDir = filepath.Dir(absPath)
81+
}
82+
}
7483

7584
// configuration reading
7685
if IsValidUrl(configFile) {
@@ -160,5 +169,16 @@ func (c *Configuration) getConfiguration(configFile string) *Configuration {
160169
c.Input.Content.Checksum[i] = strings.ToLower(c.Input.Content.Checksum[i])
161170
}
162171

172+
// normalize YARA paths relative to the configuration file directory
173+
if configBaseDir != "" {
174+
for i := 0; i < len(c.Input.Content.Yara); i++ {
175+
p := strings.TrimSpace(c.Input.Content.Yara[i])
176+
if len(p) == 0 || IsValidUrl(p) || filepath.IsAbs(p) {
177+
continue
178+
}
179+
c.Input.Content.Yara[i] = filepath.Clean(filepath.Join(configBaseDir, p))
180+
}
181+
}
182+
163183
return c
164184
}

docker/.gitignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Docker outputs
2+
output/
3+
logs/
4+
*.log
5+
6+
# Environment files (may contain secrets)
7+
.env
8+
9+
# Temporary files
10+
tmp/
11+
temp/
12+
*.tmp
13+
14+
# Build artifacts
15+
bin/
16+
17+
# OS files
18+
.DS_Store
19+
Thumbs.db
20+
desktop.ini

docker/Dockerfile.builder

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Multi-stage Dockerfile for cross-compiling FastFinder for Linux and Windows
2+
# This container builds 64-bit binaries without requiring local dependencies
3+
4+
FROM debian:bookworm-slim AS base
5+
6+
# Install common build dependencies
7+
RUN apt-get update && apt-get install -y \
8+
wget \
9+
git \
10+
build-essential \
11+
automake \
12+
libtool \
13+
pkg-config \
14+
libssl-dev \
15+
ca-certificates \
16+
&& rm -rf /var/lib/apt/lists/*
17+
18+
# Install Go 1.24.6
19+
ARG GO_VERSION=1.24.6
20+
RUN wget https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz && \
21+
tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz && \
22+
rm go${GO_VERSION}.linux-amd64.tar.gz
23+
24+
ENV PATH="/usr/local/go/bin:${PATH}"
25+
ENV GOPATH="/go"
26+
ENV PATH="${GOPATH}/bin:${PATH}"
27+
28+
# Build YARA library 4.5.5 from source (static)
29+
ARG YARA_VERSION=4.5.5
30+
WORKDIR /build
31+
RUN wget https://github.com/VirusTotal/yara/archive/v${YARA_VERSION}.tar.gz && \
32+
tar -xzf v${YARA_VERSION}.tar.gz && \
33+
cd yara-${YARA_VERSION} && \
34+
./bootstrap.sh && \
35+
./configure --prefix=/usr/local --enable-static --disable-shared && \
36+
make -j$(nproc) && \
37+
make install && \
38+
ldconfig && \
39+
cd .. && rm -rf yara-${YARA_VERSION} v${YARA_VERSION}.tar.gz
40+
41+
# ========================================
42+
# Stage 2: Linux builder
43+
# ========================================
44+
FROM base AS linux-builder
45+
46+
WORKDIR /src
47+
48+
# Copy source code
49+
COPY go.mod go.sum ./
50+
RUN go mod download
51+
52+
COPY *.go ./
53+
COPY examples ./examples/
54+
COPY resources ./resources/
55+
COPY tests ./tests/
56+
57+
# Build for Linux AMD64
58+
ENV CGO_ENABLED=1
59+
ENV GOOS=linux
60+
ENV GOARCH=amd64
61+
ENV CGO_CFLAGS="-I/usr/local/include"
62+
ENV CGO_LDFLAGS="-L/usr/local/lib -Wl,-Bstatic -lyara -Wl,-Bdynamic -lssl -lcrypto"
63+
64+
RUN go build -ldflags="-s -w" -tags yara_static -o /output/fastfinder-linux-amd64 .
65+
66+
# ========================================
67+
# Stage 3: Output collector - Linux only
68+
# ========================================
69+
FROM scratch AS binaries
70+
71+
# Copy compiled binary
72+
COPY --from=linux-builder /output/fastfinder-linux-amd64 /
73+

0 commit comments

Comments
 (0)