This repository has been archived by the owner on Apr 30, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Yevgeny Pats
committed
Aug 1, 2019
1 parent
70891dc
commit 65ffa93
Showing
19 changed files
with
914 additions
and
570 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
|
Oops, something went wrong.