Skip to content
This repository has been archived by the owner on Apr 30, 2021. It is now read-only.

Commit

Permalink
Major rewrite to cobra CLI. V2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Yevgeny Pats committed Aug 1, 2019
1 parent 70891dc commit 65ffa93
Show file tree
Hide file tree
Showing 19 changed files with 914 additions and 570 deletions.
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ builds:
- env:
- CGO_ENABLED=0
- GO111MODULE=on
main: ./cmd/fuzzit
main: ./main.go
goos:
- windows
- linux
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Also, you can use the following command to download and compile (This usually ta
```bash
git clone git@github.com:fuzzitdev/fuzzit.git
cd fuzzit
go build ./...
go build .
```

## Usage
Expand All @@ -34,6 +34,15 @@ Fuzzit CLI can be used either locally or from your CI.

Run `fuzzit --help` to get a full list of commands or checkout our [docs](https://docs.fuzzit.dev).

## Examples

Fuzzit currently supports C/C++ and Go

* [C/C++ examples](https://github.com/fuzzitdev/example-c)
* [Go examples](https://github.com/fuzzitdev/example-go)

More information can be at our [docs](https://docs.fuzzit.dev)

## Contribution

Contributions are welcome. If you need additional feature either open a github issue or a PR
Expand Down
95 changes: 95 additions & 0 deletions client/auth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package client

import (
"bytes"
"cloud.google.com/go/firestore"
"context"
"encoding/json"
"errors"
"fmt"
"golang.org/x/oauth2"
"google.golang.org/api/option"
"io/ioutil"
"os"
"time"
)

func (c * fuzzitClient) ReAuthenticate(force bool) error {
if !force {
file, err := os.Open(CacheFile)
if err != nil {
return err
}
defer file.Close()

err = json.NewDecoder(file).Decode(c)
if err != nil {
return err
}
}

if c.ApiKey == "" {
return errors.New("API Key is no configured, please run fuzzit auth [api_key]")
}

if c.IdToken == "" || (time.Now().Unix() - c.LastRefresh) > 60*45 {
createCustomTokenEndpoint := fmt.Sprintf("%s/createCustomToken?api_key=%s", FuzzitEndpoint, c.ApiKey)
r, err := c.httpClient.Get(createCustomTokenEndpoint)
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode != 200 {
return errors.New("API Key is not valid")
}

err = json.NewDecoder(r.Body).Decode(c)
if err != nil {
return err
}

r, err = c.httpClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=AIzaSyCs_Sm1VOKZwJZmTXdOCvs1wyn91vYMNSY",
"application/json",
bytes.NewBuffer([]byte(fmt.Sprintf(`{"token": "%s", "returnSecureToken": true}`, c.CustomToken))))
if err != nil {
return err
}
defer r.Body.Close()

err = json.NewDecoder(r.Body).Decode(c)
if err != nil {
return nil
}
c.LastRefresh = time.Now().Unix()

cBytes, err := json.MarshalIndent(c, "", "")
if err != nil {
return err
}
err = ioutil.WriteFile(CacheFile, cBytes, 0644)
if err != nil {
return err
}
}

token := oauth2.Token{
AccessToken: c.IdToken,
RefreshToken: c.RefreshToken,
Expiry: time.Time{},
TokenType: "Bearer",
}

tokenSource := oauth2.StaticTokenSource(&token)
ctx := context.Background()

// some known issue with go afaik
firestoreClient, err := firestore.NewClient(ctx, "fuzzit-b5fbf", option.WithTokenSource(tokenSource))
c.firestoreClient = firestoreClient

if err != nil {
return err
}

return nil
}
74 changes: 74 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package client

import (
"cloud.google.com/go/firestore"
"net/http"
"time"
)

const FuzzitEndpoint = "https://app.fuzzit.dev"
const CacheFile = "/tmp/.fuzzit.cache"


type Target struct {
Name string `firestore:"target_name"`
}

type Job struct {
TargetId string `firestore:"target_id"`
Args string `firestore:"args"`
Type string `firestore:"type"`
Host string `firestore:"host"`
Revision string `firestore:"revision"`
Branch string `firestore:"branch"`
Parallelism uint16 `firestore:"parallelism"`
AsanOptions string `firestore:"asan_options"`
UbsanOptions string `firestore:"ubsan_options"`
}


// Internal struct
type job struct {
Completed uint16 `firestore:"completed"`
Status string `firestore:"status"`
Namespace string `firestore:"namespace"`
StartedAt time.Time `firestore:"started_at,serverTimestamp"`
OrgId string `firestore:"org_id"`
Job
}


type fuzzitClient struct {
Org string
Namespace string
ApiKey string
CustomToken string
Kind string `json:"kind"`
IdToken string `json:"idToken"`
RefreshToken string `json:"refreshToken"`
ExpiresIn string `json:"expiresIn"`
LastRefresh int64
firestoreClient *firestore.Client `json:"-"`
httpClient *http.Client `json:"-"`
}


func NewFuzzitClient(apiKey string) *fuzzitClient {
c := &fuzzitClient{}
c.httpClient = &http.Client{Timeout: 60 * time.Second}
c.ApiKey = apiKey

return c
}

func LoadFuzzitFromCache() (*fuzzitClient, error) {
c := &fuzzitClient{}
c.httpClient = &http.Client{Timeout: 60 * time.Second}
err := c.ReAuthenticate(false)
if err != nil {
return nil, err
}

return c, nil
}

172 changes: 172 additions & 0 deletions client/commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package client

import (
"bytes"
"cloud.google.com/go/firestore"
"context"
"encoding/json"
"fmt"
"github.com/google/uuid"
"github.com/mholt/archiver"
"google.golang.org/api/iterator"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
)

func (c * fuzzitClient) GetResource(resource string) error {
err := c.ReAuthenticate(false)
if err != nil {
return err
}

ctx := context.Background()
rootColRef := "orgs/" + c.Org + "/"
if (len(strings.Split(resource, "/")) % 2) == 0 {
r := rootColRef + resource
docRef := c.firestoreClient.Doc(rootColRef + resource)
if docRef == nil {
return fmt.Errorf("invalid resource %s", r)
}
docsnap, err := docRef.Get(ctx)
if !docsnap.Exists() {
return fmt.Errorf("resource %s doesn't exist", resource)
}
if err != nil {
return err
}

jsonString, err := json.MarshalIndent(docsnap.Data(), "", " ")
if err != nil {
return err
}
fmt.Println(string(jsonString))
return nil
} else {
iter := c.firestoreClient.Collection(rootColRef + resource).Documents(ctx)
querySize := 0
defer iter.Stop()

for {
doc, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
return err
}
data := doc.Data()
data["id"] = doc.Ref.ID
jsonString, err := json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
fmt.Println(string(jsonString))
querySize += 1
}
if querySize == 0 {
return fmt.Errorf("no resources for %s", resource)
}
return nil
}
}

func (c * fuzzitClient) CreateTarget(targetConfig Target, seedPath string) (*firestore.DocumentRef, error) {
ctx := context.Background()
collectionRef := c.firestoreClient.Collection("orgs/" + c.Org + "/targets")
doc, _, err := collectionRef.Add(ctx,
targetConfig)
if err != nil {
return nil, err
}

if seedPath != "" {
storagePath := fmt.Sprintf("orgs/%s/targets/%s/seed", c.Org, doc.ID)
err := c.uploadFile(seedPath, storagePath, "application/gzip", "seed.tar.gz")
if err != nil {
return nil, err
}
}
return doc, nil
}

func (c * fuzzitClient) CreateJob(jobConfig Job, files [] string) (*firestore.DocumentRef, error) {
ctx := context.Background()
collectionRef := c.firestoreClient.Collection("orgs/" + c.Org + "/targets/" + jobConfig.TargetId + "/jobs")
fullJob := job{}
fullJob.Job = jobConfig
fullJob.Completed = 0
fullJob.OrgId = c.Org
fullJob.Namespace = c.Namespace
fullJob.Status = "in progress"
doc, _, err := collectionRef.Add(ctx,
fullJob)
if err != nil {
return nil, err
}
log.Println("Created new job ", doc.ID)

fuzzerPath := files[0]
splits := strings.Split(fuzzerPath, "/")
filename := splits[len(splits) - 1]
if !strings.HasSuffix(filename, ".tar.gz") {
tmpDir, err := ioutil.TempDir("", "fuzzit")
if err != nil {
return nil, err
}
_, err = copyFile(fuzzerPath, tmpDir+"/fuzzer")
if err != nil {
return nil, err
}

prefix, err := uuid.NewRandom()
if err != nil {
return nil, err
}
filesToArchive := append([]string{tmpDir + "/fuzzer"}, files[1:]...)

tmpfile := os.TempDir() + "/" + prefix.String() + ".tar.gz"
z := archiver.NewTarGz()
err = z.Archive(filesToArchive, tmpfile)
if err != nil {
return nil, err
}
fuzzerPath = tmpfile
}

storagePath := fmt.Sprintf("orgs/%s/targets/%s/jobs/%s/fuzzer", c.Org, jobConfig.TargetId, doc.ID)
err = c.uploadFile(fuzzerPath, storagePath, "application/gzip", "fuzzer.tar.gz")
if err != nil {
return nil, err
}

jsonStr := []byte(fmt.Sprintf(`{"data": {"org_id": "%s", "target_id": "%s", "job_id": "%s"}}`, c.Org, jobConfig.TargetId, doc.ID))
req, err := http.NewRequest("POST",
"https://us-central1-fuzzit-b5fbf.cloudfunctions.net/startJob",
bytes.NewBuffer(jsonStr))
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer " + c.IdToken)
req.Header.Set("Content-Type", "application/json")

res, err := httpClient.Do(req)
if err != nil {
return nil, err
}
if res.StatusCode != http.StatusOK {
bodyBytes, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Fatal(err)
}
bodyString := string(bodyBytes)
defer res.Body.Close()
return nil, fmt.Errorf(bodyString)
}
fmt.Printf("Job %s started succesfully\n", doc.ID)
defer res.Body.Close()
return doc, nil
}

Loading

0 comments on commit 65ffa93

Please sign in to comment.