# README
Usage example
go get -u github.com/ilyaglow/go-cortex
Analyze simple string type observable
package main
import (
"log"
"github.com/ilyaglow/go-cortex"
)
func main() {
// Create a client struct
client := cortex.NewClient("http://127.0.0.1:9000")
// Fill the Artifact struct
j := &cortex.Artifact{
Data: "8.8.8.8",
Attributes: cortex.ArtifactAttributes{
DataType: "ip",
TLP: 3,
},
}
// Run all analyzers over it with 1 minute timeout
reports, err := client.AnalyzeData(j, "1minute")
if err != nil {
panic(err)
}
// Iterate over channel with reports and get taxonomies
for m := range reports {
txs := m.Taxonomies()
for _, t := range txs {
log.Printf("\"%s:%s\"=\"%s\"", t.Namespace, t.Predicate, t.Value)
}
}
}
Analyze file type observable
Basically, any type that implements io.Reader
could be analyzed.
package main
import (
"log"
"os"
"github.com/ilyaglow/go-cortex"
)
func main() {
client := cortex.NewClient("http://127.0.0.1:9000")
// Open the file
fname := "filename.exe"
f, err := os.Open(fname)
if err != nil {
panic(err)
}
defer f.Close()
freports, err := client.AnalyzeData(&cortex.FileArtifact{
FileArtifactMeta: cortex.FileArtifactMeta{
DataType: "file",
TLP: 3,
},
FileName: fname,
Reader: f,
}, "5minutes")
if err != nil {
panic(err)
}
for m := range freports {
if m.Status == "Failure" {
log.Printf("%s failed with an error: %s\n", m.AnalyzerID, m.Report.ErrorMessage)
continue
}
log.Println(m.Report.FullReport)
}
}
Write your own analyzer
package main
import (
"log"
"strconv"
"github.com/ilyaglow/go-cortex"
)
// Report is a sample analyzer report
type Report struct {
Field string `json:"field,omitempty"`
Results []string `json:"results,omitempty"`
Status bool `json:"status,omitempty"`
}
func main() {
// Grab stdin to JobInput structure
input, err := cortex.NewInput()
if err != nil {
log.Fatal(err)
}
// Get url parameter from analyzer config
url, err := input.Config.GetString("url")
if err != nil {
// Report an error if something went wrong
cortex.SayError(input, err.Error())
}
// You get somehow report struct from JobInput.Data
rep, err := Do(input.Data, url)
if err != nil {
cortex.SayError(input, err.Error())
}
// Make taxonomies
var txs []cortex.Taxonomy
namespace := "AnalyzerName"
predicate := "Predicate"
if len(rep.Results) == 0 {
txs = append(txs, cortex.Taxonomy{
Namespace: namespace,
Predicate: predicate,
Level: "safe",
Value: "0",
})
} else {
txs = append(txs, cortex.Taxonomy{
Namespace: namespace,
Predicate: predicate,
Level: "suspicious",
Value: strconv.FormatInt(int64(len(rep.Results[0])), 10),
})
}
// Report accept marshallable struct and taxonomies
cortex.SayReport(rep, txs)
}
// Do represents analyzing data
func Do(input string, u string) (*Report, error) {
return &Report{
Field: "some",
Results: []string{"domain.com", "127.0.0.1", "[email protected]"},
Status: true,
}, nil
}
You can see a real world examples at https://github.com/ilyaglow/go-cortex-analyzers.
# Functions
ExtractArtifacts extracts all artifacts from report string.
NewClient bootstraps a Client If there is a need to change the http.DefaultClient you should construct a Client struct by yourself.
NewInput grabs stdin and bootstraps cortex.JobInput.
SayError returns unsuccessful Report with an error message.
SayReport constructs Report by raw body and taxonomies.
# Constants
TxInfo is an info taxonomy level.
TxMalicious is a malicious taxonomy level.
TxSafe is a safe taxonomy level.
TxSuspicious is a suspicious taxonomy level.
# Variables
Rxs represents map of regexes.
# Structs
Analyzer defines a specific Cortex Analyzer
More info: https://github.com/CERT-BDF/CortexDocs/blob/master/api/get-analyzer.md.
AnalyzerError is the report that analyzer app should return in case something went wrong.
AnalyzerReport is the report that analyzer app should return in case everything is okay.
Artifact represents a basic artifact which can be supplied for the analysis and retrieved from a job later.
ArtifactAttributes struct represents Artifact Attributes.
Client is used to deal with the API location and basic auth (in the future).
ExtractedArtifact is used for artifacts with slightly different structure.
FileArtifact represents a file observable.
FileArtifactMeta contains meta fields for FileArtifact.
Job defines an analysis job.
JobInput is used to track failed jobs and work with analyzer's input.
JobReport represents a job response.
JobsFilter is used to filter ListJobs results.
ReportBody defines a report for a given job.
Summary is a customized report object which may have taxonomies.
Taxonomy represents a taxonomy object in a report.
# Interfaces
Observable is an interface for string type artifact and file type artifact.