Skip to content

Commit

Permalink
Merge pull request #536 from pjbgf/fuzz
Browse files Browse the repository at this point in the history
Refactor Fuzz implementation
  • Loading branch information
stefanprodan authored Jan 17, 2022
2 parents 0a6505f + 50c043e commit c626836
Show file tree
Hide file tree
Showing 12 changed files with 734 additions and 19 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/cifuzz.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: CIFuzz
on:
pull_request:
branches:
- main
jobs:
Fuzzing:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Restore Go cache
uses: actions/cache@v1
with:
path: /home/runner/work/_temp/_github_home/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Smoke test Fuzzers
run: make fuzz-smoketest
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@

# Dependency directories (remove the comment below to include it)
# vendor/
testbin/
bin/
config/release/
config/crd/bases/gitrepositories.yaml
config/crd/bases/buckets.yaml

build/
21 changes: 20 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ENVTEST_ARCH ?= amd64
all: manager

# Download the envtest binaries to testbin
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
ENVTEST_ASSETS_DIR=$(shell pwd)/build/testbin
ENVTEST_KUBERNETES_VERSION?=latest
install-envtest: setup-envtest
mkdir -p ${ENVTEST_ASSETS_DIR}
Expand Down Expand Up @@ -147,3 +147,22 @@ GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef

# Build fuzzers
fuzz-build:
rm -rf $(shell pwd)/build/fuzz/
mkdir -p $(shell pwd)/build/fuzz/out/

docker build . --tag local-fuzzing:latest -f tests/fuzz/Dockerfile.builder
docker run --rm \
-e FUZZING_LANGUAGE=go -e SANITIZER=address \
-e CIFUZZ_DEBUG='True' -e OSS_FUZZ_PROJECT_NAME=fluxcd \
-v "$(shell pwd)/build/fuzz/out":/out \
local-fuzzing:latest

fuzz-smoketest: fuzz-build
docker run --rm \
-v "$(shell pwd)/build/fuzz/out":/out \
-v "$(shell pwd)/tests/fuzz/oss_fuzz_run.sh":/runner.sh \
local-fuzzing:latest \
bash -c "/runner.sh"
45 changes: 28 additions & 17 deletions controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ var (
debugMode = os.Getenv("DEBUG_TEST") != ""
)

func TestMain(m *testing.M) {
func runInContext(registerControllers func(*testenv.Environment), run func() error, crdPath string) error {
var err error
utilruntime.Must(sourcev1.AddToScheme(scheme.Scheme))
utilruntime.Must(kustomizev1.AddToScheme(scheme.Scheme))
Expand All @@ -78,9 +78,7 @@ func TestMain(m *testing.M) {
controllerLog.SetLogger(zap.New(zap.WriteTo(os.Stderr), zap.UseDevMode(false)))
}

testEnv = testenv.New(testenv.WithCRDPath(
filepath.Join("..", "config", "crd", "bases"),
))
testEnv = testenv.New(testenv.WithCRDPath(crdPath))

testServer, err = testserver.NewTempArtifactServer()
if err != nil {
Expand All @@ -89,18 +87,7 @@ func TestMain(m *testing.M) {
fmt.Println("Starting the test storage server")
testServer.Start()

controllerName := "kustomize-controller"
testEventsH = controller.MakeEvents(testEnv, controllerName, nil)
testMetricsH = controller.MustMakeMetrics(testEnv)
reconciler := &KustomizationReconciler{
ControllerName: controllerName,
Client: testEnv,
EventRecorder: testEventsH.EventRecorder,
MetricsRecorder: testMetricsH.MetricsRecorder,
}
if err := (reconciler).SetupWithManager(testEnv, KustomizationReconcilerOptions{MaxConcurrentReconciles: 4}); err != nil {
panic(fmt.Sprintf("Failed to start GitRepositoryReconciler: %v", err))
}
registerControllers(testEnv)

go func() {
fmt.Println("Starting the test environment")
Expand Down Expand Up @@ -129,7 +116,7 @@ func TestMain(m *testing.M) {
panic(fmt.Sprintf("Failed to create k8s client: %v", err))
}

code := m.Run()
runErr := run()

if debugMode {
events := &corev1.EventList{}
Expand All @@ -152,6 +139,30 @@ func TestMain(m *testing.M) {
panic(fmt.Sprintf("Failed to remove storage server dir: %v", err))
}

return runErr
}

func TestMain(m *testing.M) {
code := 0

runInContext(func(testEnv *testenv.Environment) {
controllerName := "kustomize-controller"
testEventsH = controller.MakeEvents(testEnv, controllerName, nil)
testMetricsH = controller.MustMakeMetrics(testEnv)
reconciler := &KustomizationReconciler{
ControllerName: controllerName,
Client: testEnv,
EventRecorder: testEventsH.EventRecorder,
MetricsRecorder: testMetricsH.MetricsRecorder,
}
if err := (reconciler).SetupWithManager(testEnv, KustomizationReconcilerOptions{MaxConcurrentReconciles: 4}); err != nil {
panic(fmt.Sprintf("Failed to start KustomizationReconciler: %v", err))
}
}, func() error {
code = m.Run()
return nil
}, filepath.Join("..", "config", "crd", "bases"))

os.Exit(code)
}

Expand Down
6 changes: 6 additions & 0 deletions tests/fuzz/Dockerfile.builder
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM gcr.io/oss-fuzz-base/base-builder-go

COPY ./ $GOPATH/src/github.com/fluxcd/kustomize-controller/
COPY ./tests/fuzz/oss_fuzz_build.sh $SRC/build.sh

WORKDIR $SRC
45 changes: 45 additions & 0 deletions tests/fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# fuzz testing

Flux is part of Google's [oss fuzz] program which provides continuous fuzzing for
open source projects.

The long running fuzzing execution is configured in the [oss-fuzz repository].
Shorter executions are done on a per-PR basis, configured as a [github workflow].

For fuzzers to be called, they must be compiled within [oss_fuzz_build.sh](./oss_fuzz_build.sh).

### Testing locally

Build fuzzers:

```bash
make fuzz-build
```
All fuzzers will be built into `./build/fuzz/out`.

Smoke test fuzzers:

```bash
make fuzz-smoketest
```

The smoke test runs each fuzzer once to ensure they are fully functional.

Run fuzzer locally:
```bash
./build/fuzz/out/fuzz_conditions_match
```

Run fuzzer inside a container:

```bash
docker run --rm -ti \
-v "$(pwd)/build/fuzz/out":/out \
gcr.io/oss-fuzz/fluxcd \
/out/fuzz_conditions_match
```


[oss fuzz]: https://github.com/google/oss-fuzz
[oss-fuzz repository]: https://github.com/google/oss-fuzz/tree/master/projects/fluxcd
[github workflow]: .github/workflows/cifuzz.yaml
47 changes: 47 additions & 0 deletions tests/fuzz/age_fuzzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//go:build gofuzz
// +build gofuzz

/*
Copyright 2022 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package age

import (
fuzz "github.com/AdaLogics/go-fuzz-headers"
)

// FuzzAge implements a fuzzer that targets functions within age/keysource.go.
func FuzzAge(data []byte) int {
f := fuzz.NewConsumer(data)
masterKey := MasterKey{}

if err := f.GenerateStruct(&masterKey); err != nil {
return 0
}

_ = masterKey.Encrypt(data)
_ = masterKey.EncryptIfNeeded(data)

receipts, err := f.GetString()
if err != nil {
return 0
}

_, _ = MasterKeysFromRecipients(receipts)
_, _ = MasterKeyFromRecipient(receipts)

return 1
}
Loading

0 comments on commit c626836

Please sign in to comment.