From 431fd8bd0b8770280b638becdc632523ed130504 Mon Sep 17 00:00:00 2001 From: gnmahanth Date: Tue, 29 Oct 2024 11:18:45 +0000 Subject: [PATCH] add suport for downloading rules in cli mode --- Dockerfile | 2 +- Makefile | 2 +- README.md | 27 ++++++++++++++--- core/options.go | 13 ++++++++- go.mod | 6 ++-- go.sum | 23 +++++++++++++-- main.go | 78 ++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 138 insertions(+), 13 deletions(-) diff --git a/Dockerfile b/Dockerfile index 701ada7..fec1ab4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ARG VECTORSCAN_IMG_TAG=latest ARG VECTORSCAN_IMAGE_REPOSITORY=deepfenceio FROM $VECTORSCAN_IMAGE_REPOSITORY/deepfence_vectorscan_build:$VECTORSCAN_IMG_TAG AS vectorscan -FROM golang:1.21-alpine3.18 AS builder +FROM golang:1.22-alpine3.18 AS builder MAINTAINER DeepFence RUN apk update \ diff --git a/Makefile b/Makefile index e1f30cf..ce67f8f 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ vendor: go.mod go mod vendor SecretScanner: vendor $(PWD)/**/*.go $(PWD)/agent-plugins-grpc/**/*.go - CGO_LDFLAGS="-ljansson -lcrypto -lmagic" PKG_CONFIG_PATH=/usr/local/yara/lib/pkgconfig:$(PKG_CONFIG_PATH) go build -buildmode=pie -ldflags="-s -w -extldflags=-static" -buildvcs=false -v . + CGO_LDFLAGS="-ljansson -lcrypto -lmagic" PKG_CONFIG_PATH=/usr/local/yara/lib/pkgconfig:$(PKG_CONFIG_PATH) go build -buildmode=pie -ldflags="-s -w -extldflags=-static -X 'main.version=$(DF_IMG_TAG)'" -buildvcs=false -v . .PHONY: clean bootstrap diff --git a/README.md b/README.md index 3533531..f50994f 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,29 @@ docker pull quay.io/deepfenceio/deepfence_secret_scanner_ce:2.3.0 docker pull node:8.11 ``` -* Scan the container image: - ```shell - docker run -i --rm --name=deepfence-secretscanner -v /var/run/docker.sock:/var/run/docker.sock quay.io/deepfenceio/deepfence_secret_scanner_ce:2.3.0 -image-name node:8.11 --output json > node.json - ``` +* Set Product and Licence and scan it:: +```shell +docker run -i --rm --name=deepfence-secretscanner \ + -e DEEPFENCE_PRODUCT= \ + -e DEEPFENCE_LICENSE= \ + -v /var/run/docker.sock:/var/run/docker.sock \ + quay.io/deepfenceio/deepfence_secret_scanner_ce:3.0.0 \ + --image-name node:8.11 \ + --output json > node.json +``` + +Rules can also be cached to use next run by mounting a seperate path and passing `rules-path` argument +```shell +docker run -i --rm --name=deepfence-yarahunter \ + -e DEEPFENCE_PRODUCT= \ + -e DEEPFENCE_LICENSE= \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v /tmp/rules:/tmp/rules \ + quay.io/deepfenceio/deepfence_secret_scanner_ce:3.0.0 \ + --image-name node:8.11 \ + --rules-path=/tmp/rules \ + --output json > node.json +``` # Credits diff --git a/core/options.go b/core/options.go index 5ca5273..c0b112e 100644 --- a/core/options.go +++ b/core/options.go @@ -4,6 +4,8 @@ import ( "flag" "os" "strings" + + "github.com/deepfence/YaraHunter/utils" ) const ( @@ -13,6 +15,11 @@ const ( TableOutput = "table" ) +var ( + product string = utils.GetEnvOrDefault("DEEPFENCE_PRODUCT", "ThreatMapper") + license string = utils.GetEnvOrDefault("DEEPFENCE_LICENSE", "") +) + type Options struct { Threads *int Debug *bool @@ -42,6 +49,8 @@ type Options struct { FailOnHighCount *int FailOnMediumCount *int FailOnLowCount *int + Product *string + License *string } type repeatableStringValue struct { @@ -70,7 +79,7 @@ func ParseOptions() (*Options, error) { Local: flag.String("local", "", "Specify local directory (absolute path) which to scan. Scans only given directory recursively."), HostMountPath: flag.String("host-mount-path", "", "If scanning the host, specify the host mount path for path exclusions to work correctly."), ConfigPath: flag.String("config-path", "", "yaml config path"), - RulesPath: flag.String("rules-path", "", "yara rules path"), + RulesPath: flag.String("rules-path", "/home/deepfence/usr", "yara rules path"), RulesListingURL: flag.String("rules-listing-url", "", "yara rules listing url"), FailOnCompileWarning: flag.Bool("fail-warning", false, "fail if compilation warning"), EnableUpdater: flag.Bool("enable-updated", false, "Enable rule updater"), @@ -91,6 +100,8 @@ func ParseOptions() (*Options, error) { FailOnHighCount: flag.Int("fail-on-high-count", -1, "Exit with status 1 if number of high secrets found is >= this value (Default: -1)"), FailOnMediumCount: flag.Int("fail-on-medium-count", -1, "Exit with status 1 if number of medium secrets found is >= this value (Default: -1)"), FailOnLowCount: flag.Int("fail-on-low-count", -1, "Exit with status 1 if number of low secrets found is >= this value (Default: -1)"), + Product: flag.String("product", product, "Deepfence Product type can be ThreatMapper or ThreatStryker, also supports env var DEEPFENCE_PRODUCT"), + License: flag.String("license", license, "TheratMapper or ThreatStryker license, also supports env var DEEPFENCE_LICENSE"), } flag.Parse() return options, nil diff --git a/go.mod b/go.mod index 8519603..c69b288 100644 --- a/go.mod +++ b/go.mod @@ -1,11 +1,11 @@ module github.com/deepfence/SecretScanner -go 1.21.0 +go 1.22.0 replace github.com/deepfence/agent-plugins-grpc => ./agent-plugins-grpc require ( - github.com/deepfence/YaraHunter v0.0.0-20240911101942-b2afc4495bc6 + github.com/deepfence/YaraHunter v0.0.0-20241029103149-f55d781a0919 github.com/deepfence/agent-plugins-grpc v0.0.0-00010101000000-000000000000 github.com/deepfence/golang_deepfence_sdk/client v0.0.0-20240807105002-4943c14781c5 github.com/deepfence/golang_deepfence_sdk/utils v0.0.0-20240807105002-4943c14781c5 @@ -21,6 +21,7 @@ require ( github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20231105174938-2b5cbb29f3e2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Microsoft/hcsshim v0.12.4 // indirect + github.com/VirusTotal/gyp v0.9.0 // indirect github.com/containerd/cgroups/v3 v3.0.3 // indirect github.com/containerd/containerd v1.7.19 // indirect github.com/containerd/containerd/api v1.7.19 // indirect @@ -43,6 +44,7 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect diff --git a/go.sum b/go.sum index 8f4d13a..21719e0 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/Rr4= github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ= +github.com/VirusTotal/gyp v0.9.0 h1:jhOBl93jfStmAcKLa/EcTmdPng5bn5kvJJZqQqJ5R4g= +github.com/VirusTotal/gyp v0.9.0/go.mod h1:nmcW15dQ1657PmMcG9X/EZmp6rTQsyo9g8r6Cz1/AHc= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -38,8 +40,8 @@ github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3H github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/deepfence/YaraHunter v0.0.0-20240911101942-b2afc4495bc6 h1:7Pd7dO+d0ANM504f46JCLW0BSZdg3ONchwGmz5IN7mI= -github.com/deepfence/YaraHunter v0.0.0-20240911101942-b2afc4495bc6/go.mod h1:JmkYZSkTdzS4wzqsVwUqGdTuBK1E4AZNdS/qDh0G55I= +github.com/deepfence/YaraHunter v0.0.0-20241029103149-f55d781a0919 h1:K3gxl+msEaDeiSwZyJQtFRraYLFP/k5donn+kalzy7Y= +github.com/deepfence/YaraHunter v0.0.0-20241029103149-f55d781a0919/go.mod h1:JkU6y48l2/XeYOb4iGFyTT2f9auEKU9OS49CHgEPI9k= github.com/deepfence/golang_deepfence_sdk/client v0.0.0-20240807105002-4943c14781c5 h1:Cn15C8hpx1ibMEx7ReitFQUQw1g3X5s3dfKG4AsX5Us= github.com/deepfence/golang_deepfence_sdk/client v0.0.0-20240807105002-4943c14781c5/go.mod h1:+rchMc4YNjCoHo0YAwKsT+DRBNr1hdDG0WrvAOOCc5k= github.com/deepfence/golang_deepfence_sdk/utils v0.0.0-20240807105002-4943c14781c5 h1:AfmfkTBWHHdSRj4FzYJEv48Lm8JSDzfsxhehPT5whiI= @@ -90,6 +92,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -97,6 +101,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -116,6 +121,12 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -162,11 +173,14 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -281,8 +295,11 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index e62af3e..1c0f202 100644 --- a/main.go +++ b/main.go @@ -25,11 +25,16 @@ package main // ------------------------------------------------------------------------------ import ( + "archive/tar" "context" + "encoding/json" "flag" + "io" + "io/fs" "os" "os/signal" "path" + "path/filepath" "runtime" "strconv" @@ -38,11 +43,13 @@ import ( "github.com/deepfence/SecretScanner/output" "github.com/deepfence/SecretScanner/server" log "github.com/sirupsen/logrus" + "google.golang.org/grpc" out "github.com/deepfence/YaraHunter/pkg/output" "github.com/deepfence/YaraHunter/pkg/runner" yaraserver "github.com/deepfence/YaraHunter/pkg/server" + "github.com/deepfence/YaraHunter/pkg/threatintel" pb "github.com/deepfence/agent-plugins-grpc/srcgo" ) @@ -52,7 +59,11 @@ const ( ) var ( - socketPath = flag.String("socket-path", "", "The gRPC server unix socket path") + socketPath = flag.String("socket-path", "", "The gRPC server unix socket path") + version string + checksumFile = "checksum.txt" + sourceRuleFile = "df-secret.json" + secretRuleFile = "secret.yar" ) // Read the regex signatures from config file, options etc. @@ -79,6 +90,8 @@ func main() { }, }) + log.Infof("version: %s", version) + flag.Parse() if *core.GetSession().Options.Debug { @@ -114,6 +127,11 @@ func main() { go runner.ScheduleYaraHunterUpdater(ctx, runnerOpts) } + // update rules required for cli mode + if *socketPath == "" { + updateRules(ctx, core.GetSession().Options) + } + runner.StartYaraHunter(ctx, runnerOpts, core.GetSession().ExtractorConfig, func(base *yaraserver.GRPCScannerServer) server.SecretGRPCServer { @@ -126,3 +144,61 @@ func main() { pb.RegisterSecretScannerServer(s, impl.(pb.SecretScannerServer)) }) } + +func updateRules(ctx context.Context, opts *core.Options) { + log.Infof("check and update secret rules") + + listing, err := threatintel.FetchThreatIntelListing(ctx, version, *opts.Product, *opts.License) + if err != nil { + log.Fatal(err) + } + + rulesInfo, err := listing.GetLatest(version, threatintel.SecretDBType) + if err != nil { + log.Fatal(err) + } + log.Debugf("rulesInfo: %+v", rulesInfo) + + // make sure output rules directory exists + os.MkdirAll(*opts.RulesPath, fs.ModePerm) + + // check if update required + if threatintel.SkipRulesUpdate(filepath.Join(*opts.RulesPath, checksumFile), rulesInfo.Checksum) { + log.Info("skip rules update") + return + } + + log.Info("download new rules") + content, err := threatintel.DownloadFile(ctx, rulesInfo.URL) + if err != nil { + log.Fatal(err) + } + + log.Infof("rules file size: %d bytes", content.Len()) + + // write new checksum + if err := os.WriteFile( + filepath.Join(*opts.RulesPath, checksumFile), []byte(rulesInfo.Checksum), fs.ModePerm); err != nil { + log.Fatal(err) + } + + // write rules file + outRuleFile := filepath.Join(*opts.RulesPath, secretRuleFile) + threatintel.ProcessTarGz(content.Bytes(), sourceRuleFile, outRuleFile, processSecretRules) +} + +func processSecretRules(header *tar.Header, reader io.Reader, outPath string) error { + + var fb threatintel.FeedsBundle + if err := json.NewDecoder(reader).Decode(&fb); err != nil { + log.Error(err) + return err + } + + if err := threatintel.ExportYaraRules(outPath, fb.ScannerFeeds.SecretRules, fb.Extra); err != nil { + log.Error(err) + return err + } + + return nil +}