11package client
22
33import (
4+ "cloud.google.com/go/firestore"
45 "context"
56 "encoding/json"
67 "fmt"
8+ "github.com/docker/docker/api/types"
9+ "github.com/docker/docker/api/types/container"
10+ "github.com/docker/docker/pkg/stdcopy"
11+ "github.com/google/uuid"
12+ "github.com/mholt/archiver"
13+ "google.golang.org/api/iterator"
14+ "io"
715 "io/ioutil"
816 "log"
917 "os"
1018 "path/filepath"
1119 "strings"
12-
13- "cloud.google.com/go/firestore"
14- "github.com/google/uuid"
15- "github.com/mholt/archiver"
16- "google.golang.org/api/iterator"
20+ //"github.com/docker/docker/api/types/container"
21+ "github.com/docker/docker/client"
22+ //"github.com/docker/docker/pkg/stdcopy"
1723)
1824
25+ func (c * fuzzitClient ) archiveFiles (files []string ) (string , error ) {
26+ fuzzerPath := files [0 ]
27+ filename := filepath .Base (fuzzerPath )
28+ if ! strings .HasSuffix (filename , ".tar.gz" ) {
29+ tmpDir , err := ioutil .TempDir ("" , "fuzzit" )
30+ if err != nil {
31+ return "" , err
32+ }
33+ dstPath := filepath .Join (tmpDir , "fuzzer" )
34+ _ , err = copyFile (dstPath , fuzzerPath )
35+ if err != nil {
36+ return "" , err
37+ }
38+
39+ prefix , err := uuid .NewRandom ()
40+ if err != nil {
41+ return "" , err
42+ }
43+ filesToArchive := append ([]string {dstPath }, files [1 :]... )
44+
45+ tmpfile := filepath .Join (os .TempDir (), prefix .String ()+ ".tar.gz" )
46+ z := archiver .NewTarGz ()
47+ err = z .Archive (filesToArchive , tmpfile )
48+ if err != nil {
49+ return "" , err
50+ }
51+ fuzzerPath = tmpfile
52+ }
53+
54+ return fuzzerPath , nil
55+ }
56+
57+ func (c * fuzzitClient ) DownloadSeed (dst string , target string ) error {
58+ storagePath := fmt .Sprintf ("orgs/%s/targets/%s/seed" , c .Org , target )
59+ err := c .downloadFile (dst , storagePath )
60+ if err != nil {
61+ return err
62+ }
63+ return nil
64+ }
65+
66+ func (c * fuzzitClient ) DownloadCorpus (dst string , target string ) error {
67+ storagePath := fmt .Sprintf ("orgs/%s/targets/%s/corpus" , c .Org , target )
68+ err := c .downloadFile (dst , storagePath )
69+ if err != nil {
70+ return err
71+ }
72+ return nil
73+ }
74+
75+ func (c * fuzzitClient ) DownloadFuzzer (dst string , target string , job string ) error {
76+ storagePath := fmt .Sprintf ("orgs/%s/targets/%s/jobs/%s/fuzzer" , c .Org , target , job )
77+ err := c .downloadFile (dst , storagePath )
78+ if err != nil {
79+ return err
80+ }
81+ return nil
82+ }
83+
1984func (c * fuzzitClient ) GetResource (resource string ) error {
20- err := c .ReAuthenticate ( false )
85+ err := c .refreshToken ( )
2186 if err != nil {
2287 return err
2388 }
@@ -74,9 +139,14 @@ func (c *fuzzitClient) GetResource(resource string) error {
74139}
75140
76141func (c * fuzzitClient ) CreateTarget (targetName string , seedPath string ) (* firestore.DocumentRef , error ) {
142+ err := c .refreshToken ()
143+ if err != nil {
144+ return nil , err
145+ }
146+
77147 ctx := context .Background ()
78148 docRef := c .firestoreClient .Doc ("orgs/" + c .Org + "/targets/" + targetName )
79- _ , err : = docRef .Get (ctx )
149+ _ , err = docRef .Get (ctx )
80150 if err == nil {
81151 return nil , fmt .Errorf ("target %s already exist" , targetName )
82152 }
@@ -97,9 +167,116 @@ func (c *fuzzitClient) CreateTarget(targetName string, seedPath string) (*firest
97167 return docRef , nil
98168}
99169
100- func (c * fuzzitClient ) CreateJob (jobConfig Job , files []string ) ( * firestore. DocumentRef , error ) {
170+ func (c * fuzzitClient ) CreateLocalJob (jobConfig Job , files []string ) error {
101171 ctx := context .Background ()
172+ cli , err := client .NewClientWithOpts (client .FromEnv )
173+ if err != nil {
174+ return err
175+ }
176+ cli .NegotiateAPIVersion (ctx )
102177
178+ fuzzerPath , err := c .archiveFiles (files )
179+ if err != nil {
180+ return err
181+ }
182+
183+ fuzzer , err := os .Open (fuzzerPath )
184+ if err != nil {
185+ return err
186+ }
187+
188+ corpusPath := fmt .Sprintf ("orgs/%s/targets/%s/corpus.tar.gz" , c .Org , jobConfig .TargetId )
189+ log .Print (corpusPath )
190+ corpusLink , err := c .getStorageLink (corpusPath , "read" )
191+ if err != nil {
192+ return err
193+ }
194+
195+ seedPath := fmt .Sprintf ("orgs/%s/targets/%s/seed" , c .Org , jobConfig .TargetId )
196+ seedLink , err := c .getStorageLink (seedPath , "read" )
197+ if err != nil {
198+ return err
199+ }
200+
201+ log .Println ("Pulling container" )
202+ reader , err := cli .ImagePull (ctx , "docker.io/fuzzitdev/fuzzit:stretch-llvm9" , types.ImagePullOptions {})
203+ if err != nil {
204+ return err
205+ }
206+ _ , err = io .Copy (os .Stdout , reader )
207+ if err != nil {
208+ return err
209+ }
210+
211+ log .Println ("Creating container" )
212+ createdContainer , err := cli .ContainerCreate (ctx , & container.Config {
213+ Env : []string {
214+ "CORPUS_LINK=" + corpusLink ,
215+ "SEED_LINK=" + seedLink ,
216+ "ASAN_OPTIONS=" + jobConfig .AsanOptions ,
217+ "UBSAN_OPTIONS=" + jobConfig .UbsanOptions ,
218+ "ARGS=" + jobConfig .Args },
219+ Image : "docker.io/fuzzitdev/fuzzit:stretch-llvm9" ,
220+ AttachStdin : true ,
221+ }, nil , nil , "" )
222+ if err != nil {
223+ return err
224+ }
225+
226+ log .Println ("Uploading fuzzer to container" )
227+ err = cli .CopyToContainer (ctx , createdContainer .ID , "/app/" , fuzzer , types.CopyToContainerOptions {
228+ AllowOverwriteDirWithFile : true ,
229+ })
230+ if err != nil {
231+ return err
232+ }
233+
234+ log .Println ("Starting the container" )
235+ err = cli .ContainerStart (ctx , createdContainer .ID , types.ContainerStartOptions {})
236+ if err != nil {
237+ return err
238+ }
239+
240+ out , err := cli .ContainerLogs (ctx , createdContainer .ID , types.ContainerLogsOptions {
241+ ShowStdout : true ,
242+ ShowStderr : true ,
243+ Follow : true ,
244+ })
245+ if err != nil {
246+ return err
247+ }
248+
249+ stdcopy .StdCopy (os .Stdout , os .Stderr , out )
250+
251+ log .Println ("Waiting for container" )
252+ statusCh , errCh := cli .ContainerWait (ctx , createdContainer .ID , container .WaitConditionNotRunning )
253+ select {
254+ case err := <- errCh :
255+ if err != nil {
256+ cli .ContainerRemove (ctx , createdContainer .ID , types.ContainerRemoveOptions {})
257+ return err
258+ }
259+ case status := <- statusCh :
260+ if status .StatusCode != 0 {
261+ cli .ContainerRemove (ctx , createdContainer .ID , types.ContainerRemoveOptions {})
262+ return fmt .Errorf ("fuzzer exited with %d" , status .StatusCode )
263+ }
264+ }
265+
266+ err = cli .ContainerRemove (ctx , createdContainer .ID , types.ContainerRemoveOptions {})
267+ if err != nil {
268+ return err
269+ }
270+
271+ return nil
272+ }
273+
274+ func (c * fuzzitClient ) CreateJob (jobConfig Job , files []string ) (* firestore.DocumentRef , error ) {
275+ err := c .refreshToken ()
276+ if err != nil {
277+ return nil , err
278+ }
279+ ctx := context .Background ()
103280 collectionRef := c .firestoreClient .Collection ("orgs/" + c .Org + "/targets/" + jobConfig .TargetId + "/jobs" )
104281 fullJob := job {}
105282 fullJob .Job = jobConfig
@@ -141,7 +318,7 @@ func (c *fuzzitClient) CreateJob(jobConfig Job, files []string) (*firestore.Docu
141318
142319 storagePath := fmt .Sprintf ("orgs/%s/targets/%s/jobs/%s/fuzzer" , c .Org , jobConfig .TargetId , jobRef .ID )
143320 log .Println ("Uploading fuzzer..." )
144- err : = c .uploadFile (fuzzerPath , storagePath , "application/gzip" , "fuzzer.tar.gz" )
321+ err = c .uploadFile (fuzzerPath , storagePath , "application/gzip" , "fuzzer.tar.gz" )
145322 if err != nil {
146323 return nil , err
147324 }
0 commit comments